React生命周期函数
- 一、挂载阶段(Mounting)
- 1. constructor
- 2. componentWillMount
- 3. render
- 4.componentDidMount
- 二、更新阶段(Updating)
- 1. componentWillReceiveProps(nextProps)
- 2. shouldComponentUpdate(nextProps,nextState)
- 3. componentWillUpdate(nextProps,nextState)
- 4. render
- 5. componentDidUpdate(prevProps,prevState)
- 三、卸载阶段(Unmounting)
- componentWillUnmount
组件从创建到被销毁的过程称为 组件生命周期。React为组件在不同的生命周期阶段提供了不同的生命周期方法,让developer可以在组件的生命周期过程中更好地控制组件行为。组件生命周期被分为三个阶段: 挂载阶段、 更新阶段、 卸载阶段。React生命周期具体代码实现详见: React组件API参考文档。React16.8的新增特性Hook生命周期使用 Effect Hook,代码实现详见: 如何使用Effect Hook。
一、挂载阶段(Mounting)
这个阶段组件被创建,执行初始化,并被挂载到dom中,完成组件的第一次渲染。依次调用的生命周期方法有:
- constructor
- getInitialState
- componentWillMount
- render
- componentDidMount
1. constructor
这是ES6 class的构造方法,组件被创建时,会首先调用组件的构造方法。当然,并不是每个组件都需要定义自己的构造函数,无状态的React组件往往就不需要定义构造函数,
执行时间:组件被加载前最先调用,并且只调用一次。
作用:
- 继承父组件的Props
super(props) - 初始化state
组建生命周期中任何函数都可能要访问state,那么整个生命周期中第一个被调用的构造函数自然是初始化state最理想的地方;
this.state={变量名:值} - 绑定成员函数的this环境
this.函数名称 = this.函数名称.bind(this),目的在于,在render中调用时,可直接使用this.函数名称。
//首先这里继承了PureComponent 则意味着该组件使用了shouldComponentUpdate方法
class ListOfWords extends React.PureComponent {
render() {
return <div>{this.props.words.join(',')}</div>;
}
}
class WordAdder extends React.Component {
constructor(props) {
super(props);
this.state = {
words: ['marklar']
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
// This section is bad style and causes a bug
const words = this.state.words;
words.push('marklar');//数组的push方法返回的并不是一个新数组
this.setState({words: words});
}
render() {
return (
<div>
<button onClick={this.handleClick} />
<ListOfWords words={this.state.words} />
</div>
);
}
}
2. componentWillMount
组件被挂载在DOM(render)之前调用,且只被调用一次。在这个方法中调用this.setState不会引起组件的重新渲染。
3. render
React组件必不可少的核心组件,不能在该函数中修改状态state。
- 执行时间:componentWillMount之后,componentDidMount之前,
- 作用:渲染挂载组件
- 触发条件:(1)初始化加载页面(2)状态机改变setState ( 3 ) 接收到新的props(父组件更新)
注:render函数并不做实际的渲染动作,组件在render中生成虚拟的DOM节点,即JSX,最后由React生成真实的DOM节点。
4.componentDidMount
组件被挂载在DOM之后调用,且只被调用一次。这时候已经可以获取到DOM结构,因此依赖DOM节点的操作可以放到这个方法中,还可以用于像服务器请求数据。这个方法中调用this.setState会引起组件的重新渲染。
二、更新阶段(Updating)
当组件被装载到DOM树之后,props或者state被修改可以引发组件更新。props引起的组件更新,本质上是由渲染该组件的父组件引起的,也就是当父组件的render方法被调用时,组件会发生更新过程,这个时候,组件props的值可能改变也可能没有发生改变,因为父组件可以使用相同的对象或值为组件props赋值。但无论props是否改变,父组件的render方法每一次调用,都会导致组件更新。state引起的组件更新,是通过调用this.setState修改组件state来触发的。组件更新阶段,依次调用的生命周期方法有:
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
1. componentWillReceiveProps(nextProps)
这个方法只在props引起的组件更新过程中,才会被调用。state引起的组件更新并不会触发该方法执行。参数nextProps是父组件传递给当前组建新的props,它的值可能与子组件当前props值相等,往往需比较nextProps和this.props来决定是否执行props变化之后的逻辑。
2. shouldComponentUpdate(nextProps,nextState)
这个方法决定组件是否继续执行更新过程。方法返回true(默认返回值),组件继续执行更新过程;返回false,组件更新过程停止,后续componentWillUpdate之类的方法也不会被调用。一般通过比较nextProps、nextState和组件当前props、state决定这个方法返回结果。这个方法可减少组件不必要渲染,从而优化组件性能。
上代码:
//该方法可以在继承Component类时自定义代码如下:
class CounterButton extends React.Component { //继承Component类
constructor(props) {
super(props);
this.state = {count: 1};
}
//自定义shouldComponentUpdate方法
shouldComponentUpdate(nextProps, nextState) {
if (this.props.color !== nextProps.color) {
return true;
}
if (this.state.count !== nextState.count) {
return true;
}
return false;
}
render() {
return (
<button
color={this.props.color}
onClick={() => this.setState(state => ({count: state.count + 1}))}>
Count: {this.state.count}
</button>
);
}
}
3. componentWillUpdate(nextProps,nextState)
此方法在组件render调用前执行,可以作为组件更新发生前执行某些工作的地方,一般很少用到。
4. render
上面介绍过,这里不作多余赘述。
5. componentDidUpdate(prevProps,prevState)
组件更新后被调用,可以操作更新后的DOM。两个参数代表组件更新前的props和state.
三、卸载阶段(Unmounting)
组件从DOM中被卸载的过程,只有一个生命周期方法:
- componentWillUnmount
componentWillUnmount
这个方法在组件被卸载之前调用,可以在这里执行一些清理工作是,比如清除组件中使用的定时器,清除componentDidMount中手动创建的DOM元素等,以避免内存泄漏。
注:只有类组件才具有生命周期的方法,函数组件没有生命周期的方法,因此永远不要在函数组件中使用生命周期方法。
番外篇:此为作者第一篇博客,博客内容主要是在项目过程中总结的学习笔记和踩过的坑,供大家借鉴学习。还有一点,平时一定要注意思考和总结,重要的事情说三遍,思考总结!思考总结!思考总结!