共计 4597 个字符,预计需要花费 12 分钟才能阅读完成。
React16.3.0 开始,生命周期进行了一些变化。本文主要介绍 React16.3.0 之后的生命周期。
React16.3.0 之前生命周期:
16 版本之前的 react 组件的生命周期相信大家已经很熟悉。16 版本的 react 对组件的生命周期函数进行了一些修改, 下面进行详细说明。
React16.3.0 之前生命周期
创建期:
constructor(props, context)
componentWillMount()
render()
componentDidMount()
运行时:
props 发生变化时
componentWillReceiveProps(nextProps, nextContext)
shouldComponentUpdate(nextProps, nextState, nextContext)
componentWillUpdate(nextProps, nextState, nextContext)
render
componentDidUpdate(prevProps, prevState, snapshot)
state 发生变化时
shouldComponentUpdate(nextProps, nextState, nextContext)
componentWillUpdate(nextProps, nextState, nextContext)
render
componentDidUpdate(prevProps, prevState, snapshot)
卸载时
componentWillUnmount()
React16.3.0 之后的生命周期
创建期:
constructor(props, context)
static getDerivedStateFromProps(props, status)
render()
componentDidMount()
或者如下生命周期:
constructor(props, context)
componentWillMount() / UNSAFE_componentWillMount()
render()
componentDidMount()
注意: getDerivedStateFromProps/getSnapshotBeforeUpdate 和 componentWillMount/componentWillReceiveProps/componentWillUpdate 如果同时存在,React 会在控制台给出警告信息,且仅执行 getDerivedStateFromProps/getSnapshotBeforeUpdate【React@16.7.0】
运行时:
props 发生变化时
static getDerivedStateFromProps(props, status)
shouldComponentUpdate(nextProps, nextState, nextContext)
render
getSnapshotBeforeUpdate(prevProps, prevState)
componentDidUpdate(prevProps, prevState, snapshot)
或者如下生命周期:
componentWillReceiveProps(nextProps, nextContext)/UNSAFE_componentWillReceiveProps
shouldComponentUpdate(nextProps, nextState, nextContext)
componentWillUpdate(nextProps, nextState, nextContext)
render
componentDidUpdate(prevProps, prevState, snapshot)
state 发生变化时
static getDerivedStateFromProps(props, status)
shouldComponentUpdate(nextProps, nextState, nextContext)
render
getSnapshotBeforeUpdate(prevProps, prevState)
componentDidUpdate(prevProps, prevState, snapshot)
或者如下生命周期:
shouldComponentUpdate(nextProps, nextState, nextContext)
componentWillUpdate(nextProps, nextState, nextContext)/UNSAFE_componentWillUpdate
render
componentDidUpdate(prevProps, prevState, snapshot)
销毁时
componentWillUnmount()
新的生命周期图示:
生命周期详解
1.constructor(props, context)
constructor 生命周期,如不需要,可缺省。通常会在 constructor 方法中初始化 state 和绑定事件处理程序。但是,如果写了 constructor,那么必须在其中调用 super(props); 否则可能会引起报错。
如:
class Base extends Component {
constructor(props) {
super(); // 应该为 super(props);
}
state = {
name: this.props.name
}
//….code
}
抛出异常: Uncaught TypeError: Cannot read property ‘name’ of undefined.
同样,如果定义了 context, 在 state 中需要使用 this.context 去获取 context 上的内容,则需要 super(props, context);
不过,如果你缺省 constructor, 那么在 state 中,可以放心的使用 this.props 或者是 this.context,不会引起报错。
class Base extends Component {
state = {
name: this.props.name,
color: this.context.color
}
//….code
}
初始化的 state 同样可以在 constructor 中定义。如果需要给方法绑定 this,那么统一在 constructor 中进行。
2.static getDerivedStateFromProps(props, state)
当组件的 state 需要根据 props 来改变的时候可调用此方法。这个方法是在 render() 前会被执行,每次触发 render 前,都会触发此方法。
该方法有两个参数 props 和 state; 返回值为 state 对象, 不需要返回整体 state,把需要改变的 state 返回即可。如果不需要,可以返回 null.
class Base extends Component {
state = {
age: 20
}
static getDerivedStateFromProps(props, state) {
return {
age: 50
}
}
render() {
// 50
return (
<div>{this.state.age}</div>
)
}
}
这个方法允许组件基于 props 的变更来更新其内部状态, 以这种方式获得的组件状态被称为派生状态。应该谨慎使用派生状态,可能会引入潜在的错误
3.render
React 组件中必须要提供的方法。当 state 或者 props 任一数据有更新时都会执行。
render() 是一个纯函数,因此,不要在其中执行 setState 诸如此类的操作。render 必须有一个返回值,返回的数据类型可以有:
null、String、Number、Array、Boolean。
React elements
Fragment
Portal
注意不要在 render 中调用 setState
4.componentDidMount
componentDidMount() 方法是在组件加载完后立即执行,也就是当该组件相关的 dom 节点插入到 dom 树中时。该方法在组件生命中只执行一次。一般情况,我们会在这里 setState(), 或者进行接口请求,设置订阅等。
class Base extends Component {
state = {
age: 20
}
componentDidMount() {
this.fetchDate();
}
render() {
return (
<div>{this.state.age}</div>
)
}
//other code
}
5.shouldComponentUpdate(nextProps, nextState, nextContext)
在渲染新的 props 或 state 前,shouldComponentUpdate 被调用,默认返回 true。forceUpdate() 时不会调用此方法。
如果 shouldComponentUpdate() 返回 false,那么 getSnapshotBeforeUpdate,render 和 componentDidUpdate 不会被调用。
此生命周期主要用于优化性能。
6.getSnapshotBeforeUpdate(prevProps, prevState)
在 render() 的输出被渲染到 DOM 之前被调用。使组件能够在它们被更改之前捕获当前值(如滚动位置)。这个生命周期返回的任何值都将作为第三个参数传递给 componentDidUpdate().
7.componentDidUpdate(prevProps, prevState, snapshot)
在更新发生后调用 componentDidUpdate()。当组件更新时,将此作为一个机会来操作 DOM。如将当前的 props 与以前的 props 进行比较(例如,如果 props 没有改变,则可能不需要网络请求。
如果组件使用 getSnapshotBeforeUpdate(),则它返回的值将作为第三个“快照”参数传递给 componentDidUpdate()。否则,这个参数是 undefined。
8.componentWillUnmount()
在组件被卸载并销毁之前立即被调用。在此方法中执行任何必要的清理,例如使定时器无效,取消网络请求或清理在 componentDidMount()中创建的任何监听。
最后,说明一点:
componentWillUpdate,componentWillReceiveProps,componentWillUpdate 这三个生命周期在 React 未来版本中会被废弃。
而 UNSAFE_componentWillUpdate,UNSAFE_componentWillReceiveProps,UNSAFE_componentWillUpdate 未来版本中仍可继续使用。
初始化阶段 (父组件和子组件):
运行阶段: 父组件 props/state 更新
子组件的 shouldComponentUpdate 返回 false,则子组件其后的生命周期都不在进行,但是父组件的生命周期继续执行。
卸载阶段: 卸载父组件
参考:
https://segmentfault.com/a/11…
https://www.jianshu.com/p/514…
https://blog.csdn.net/qq_2931…