react系列-class组件生命周期
react": "^17.0.2"
生命周期函数介绍
constructor
组件初始化执行构造函数,只执行一次。
继承Component则必须显式调用super(props),否则this.props会出现未定义bug。
可在其中声明state。
constructor(props) {
super(props);
this.state = {
text:''
};
}
getDerivedStateFromProps
该函数返回一个对象,会合并到state中,返回null则不更新state。
组件挂载和更新阶段都会调用。
此方法适用于罕见的用例,即 state 的值在任何时候都取决于 props。
/**
* 该函数返回一个对象,会合并到state中。
* @param {*} nextProps
* @param {*} prevState 如果由于父组件更新触发该函数,则是preState。如果是子组件自身更新触发该函数,则是nextState
*/
static getDerivedStateFromProps(nextProps, prevState) {
return {
parentText: nextProps.text,
};
}
shouldComponentUpdate
函数返回一个布尔值。true则执行后续流程,false则不执行render函数及其后续生命周期函数。
常用于性能优化。
/**
* 根据返回值来判断是否执行后续的生命周期函数,是否对组件进行re-render(重渲染)
* @param {object} nextProps
* @param {object} nextState
*/
shouldComponentUpdate(nextProps, nextState) {
console.log('Child组件的shouldComponentUpdate()');
return true;
}
render
返回一个VNode、VNode数组或framgments、Portals、字符串或者数字、布尔类型或者null则什么都不渲染。
不可执行setState,否则会造成死循环。
render() {
return (
<div className="child-container">
<p>Child组件的text:{this.state.text}</p>
</div>
);
}
getSnapshotBeforeUpdate
在更新之前获取state的快照,此时可以获取Dom信息。
只有在更新阶段会执行。
使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期方法的任何返回值将作为参数传递给
componentDidUpdate()。此用法并不常见,但它可能出现在 UI 处理中,如需要以特殊方式处理滚动位置的聊天线程等。
/**
* Pre-commit阶段:可以读取DOM
* 返回值作为componentDidUpdate生命周期函数的第三个参数
* @param {object} prevProps
* @param {object} prevState
*/
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log('Child组件的getSnapshotBeforeUpdate()', prevProps, prevState);
return {
value: 'getSnapshotBeforeUpdate',
};
}
componentDidMount
组件加载完之后执行,适合执行包含副作用的函数,例如请求数据和设置事件监听等。
/**
* 组件挂载完之后执行,适合执行包含副作用的函数
*/
componentDidMount() {
console.log('Child组件的componentDidMount()');
}
componentDidUpdate
组件更新完毕之后执行。
注意如果在这个函数中设置state,需要在一定的条件下执行,否则可能引发死循环。
/**
* 组件更新完毕之后执行
* @param {object} prevProps
* @param {object} prevState
* @param {*} valueFromSnapshot
*/
componentDidUpdate(prevProps, prevState, valueFromSnapshot) {
console.log(
'组件的componentDidUpdate()',
'从组件的getSnapshotBeforeUpdate获得的值',
prevProps,
prevState,
valueFromSnapshot
);
}
componentWillUnMount
组件卸载前执行该生命周期函数。
/**
* 组件卸载前执行该生命周期函数
* 执行场景:
* 1.组件在父组件中移除了
* 2.组件中设置了key值,父组件在render过程中,发现子组件两次key值不同
*/
componentWillUnmount() {
console.log('Child组件的componentWillUnmount()');
}
父子组件渲染流程
分为挂载阶段、更新阶段、卸载阶段来进行分析。
挂载阶段
触发流程:
- 执行父组件挂载时的"Render阶段"生命周期函数(constructor->getDerivedStateFromProps->render)
- 执行子组件挂载时的“Render阶段”生命周期函数(constructor->getDerivedStateFromProps->render)
- 执行子组件挂载时的“Commit阶段”生命周期函数(componentDidMount)
- 执行父组件挂载时的“Commit阶段”生命周期函数(componentDidMount)
有种类似于JS事件执行机制:先捕获,后冒泡
更新阶段
来自子组件的更新
只会触发子组件自身的更新阶段的生命周期函数,不会触发父组件的任何生命周期函数。
触发流程:
- 执行子组件更新阶段生命周期函数getDerviedStateFromProps
- 执行子组件更新阶段生命周期函数shouldComponentUpdate
- 执行子组件更新阶段生命周期函数render
- 执行子组件更新阶段生命周期函数getSnapshotBeforeUpdate
- 执行子组件更新阶段生命周期函数componentDidUpdate
来自父组件的更新
类似挂载阶段生命周期函数的触发流程,但是getSnapshotBeforeUpdates生命周期函数特殊。
触发流程:
- 执行父组件更新阶段生命周期函数(getDerviedStateFromProps -> shouldComponentUpdate -> render)
- 执行子组件更新阶段生命周期函数(getDerviedStateFromProps -> shouldComponentUpdate -> render)
- 执行子组件更新阶段生命周期函数getSnapshotBeforeUpdate
- 执行父组件更新阶段生命周期函数getSnapshotBeforeUpdate
- 执行子组件更新阶段生命周期函数componentDidUpdate
- 执行父组件更新阶段生命周期函数componentDidUpdate
还是和事件冒泡机制类似,但是当子组件getSnapshotBeforeUpdate生命周期触发后,会立刻触发父组件同样的生命周期。之后再回到子组件生命周期中
卸载阶段
组件卸载只会触发该组件的componentWillUnmount生命周期函数
\