React 世界中,组成一个页面的最小单元为一个个组件,很显然如何合理的创建它们是个非常关键的点。下面介绍一下我对三种创建组件方式的理解与总结。
从简单开始:函数式组件
了解过 React 的人都知道,一个 Component 数据源有两个:
- 来自外部的属性(props)
- 来自内部的状态(State)
当函数式的创建一个组件之后,显然它已经注定了没法再拥有自己的 State 了,只能 “无脑” 的去获取属性内容并展示,因为函数式组件其实是一个只实现了 render 函数的组件。
所以把这种组件称之为 “小傻瓜组件” 非常的形象
一个 “傻瓜函数式组件” 的例子:
// 这一句导入必须添加, JSX 语境依赖于此
import React from 'react';
export default ({order="没人下达命令,我就啥也不干"}) => {
return (
<div>
我是“傻瓜组件”,我完全服从命令:{order}.
</div>
);
};
复制代码
这个简单的组件只接受一个 order 的 ,并且为这个属性设置了一个默认值。
- 当使用这个组件的地方为它设置了 order 属性,就会打印外部设置的order属性值;
- 如果没有设置,就会打印这个默认值(ES6 语法允许给定义的函数参数设置一个默认值)
这里使用了 ES6 箭头语法,快速的创建了一个无状态的函数式组件并 exoprt 出去供外界使用。
复杂点的:继承 React Component 相关类实现
React 版本16以后,官方已经不推荐使用 createclass 的方式创建组件了,同时也取消了以前 Mixin 那一套侵入式复用代码的做法,转而推荐大家使用高阶函数的方式来实现对代码的复用
继承的方式创建一个组件可以继承两个父类:
- React.Component
- React.PureComponent
PureComponent 和 Component 除了在 shouldComponentUpdate 方法的实现逻辑上不一样,其他表现都一样,PureComponent使用了props和state的浅比较。
一般情况下我们选择继承 React.PureComponent 可以优化我们的组件性能,不过特殊时候你也可以选择继承 React.Component,然后自己去实现 shouldComponentUpdate 方法的逻辑部分。
相比“傻瓜式”组件,继承方式获得的组件更加 “聪明” 了:
1.它可以有自己的属性 2.它可以有自己的状态 3.它可以有自己的生命周期逻辑
一个简单的 “聪明的” 继承式的组件例子:
import React from "react";
import PropTypes from "prop-types";
export default class ComponentOne extends React.PureComponent {
static defaultProps = {
propOne: "默认属性"
};
static propTypes = {
propOne: PropTypes.string.isRequired
};
constructor(props) {
super(props);
console.log("构造函数");
this.clickToAdd = this.clickToAdd.bind(this);
this.state = {
count: 0
};
}
clickToAdd() {
this.setState({
count: this.state.count + 1
});
}
componentDidMount() {
console.log("界面装载完成");
}
render() {
return (
<div>
<div>
我是由继承 React.PureComponent 创建的组件。并且我有属性:{this.props.propOne}
</div>
<div>
当前计数:{this.state.count}
</div>
<div>
<button onClick={this.clickToAdd}>点击计数增加</button>
</div>
</div>
);
}
}
复制代码
需要注意的一点,使用继承的方式创建的组件,它的成员函数都不会自动绑定 this,推荐在构造函数 constructor 中进行手动 bind。
上面代码中的组件有自己的状态,有自己的属性,也自己实现了生命周期函数中的 componentDidMount,在里面简单打印了一句 log。
更厉害的:高阶组件 HOC(Higher Order Component)
高阶组件,我的理解就是一个能接受组件为参数,并能返回一个新组件的函数。高阶组件有下面两种实现方式: