# react 组件生命周期
# react16前的生命周期
在react16的之前生命周期其实主要分为四个阶段:组件初始化、组件挂载、组件更新、组件卸载。
# 组件初始化阶段
# constructor
在该阶段组件中的构造方法 constructor() 接受 props 接收父组件传下来的 props。还可以在 constructor() 内部定义定义this.state 的初始内容。注意:在组件中写了 constructor 方法就必须在里面使用 super(),并且应在其他语句之前前调用 super(props)。否则,this.props 在构造函数中可能会出现未定义的 bug。
constructor(props) {
super(props)
console.log(this.props) // 在内部可以使用props
this.state = {
//定义state初始值
}
}
2
3
4
5
6
7
# 组件挂载阶段
# componentWillMount
在组件将要挂载到 DOM 前调用,只会被调用一次,在该方法中修改 state 的值,并不会引起组件重新渲染。(数据请求等异步操作不建议写在该方法内,异步操作可能阻塞 UI)。
componentWillMount(){}
# render()
该函数会创建一个虚拟 DOM,用来表示组件的输出。只能通过 this.props 和 this.state 访问数据,且不能在里面执行 this.setState 更该组件状态。在 render 中可以返回 null、false 或者任何 React 组件,只能出现一个顶级组件,不能返回一组元素(在 react16 中有所改善,可以返回一组元素或单个字符串)。
Render(){
return (
// react组件
)
}
2
3
4
5
# componentDidMount
组件挂载到 Dom 后调用,且只调用一次。此时组件已经生成对应的 DOM 结构,可以在该函数中通过ReactDOM.findDOMNode()访问到真实的 DOM 或者通过 this.refs.[refName] 属性获取真实 DOM 。(数据请求等异步操作建议写在该方法内)
componentDidMount() {
// 进行异步数据请求或者获取dom
}
2
3
# 组件更新阶段
# componentWillReceiveProps
该函数接受一个参数 nextProps,当父组件重传props时会调用。拿到新的 props 与旧的 props 来比较是否变化,若变化可以通过 this.setState 更新 state。当然也可以不比较新旧 props 值直接更新 state。
componentWillReceiveProps(nextProps) {
// 示例
if (nextProps.state !== this.props.state) {
this.setState({
state: nextProps.state
});
}
}
2
3
4
5
6
7
8
官方提示:在componentWillReceiveProps中调用 this.setState() 将不会引起第二次渲染。
由于每次子组件接收到新的props,都会重新渲染一次,除非你使用 shouldComponentUpdate 来阻止重新渲染,但是你可以 componentWillReceiveProps 中根据新的 props 更新 state,虽然更新state也会触发一次重新渲染,但并不会触发额外的render。
# shouldComponentUpdate(nextProps,nextState)
该函数是唯一可以控制组件渲染的生命周期。如果 props 和 state 的改变不需要重新渲染组件。则可以在该函数内返回 false,阻止组件的重新渲染。为了优化组件性能,减少组件的不必要渲染。
shouldComponentUpdate(nextProps, nextState){
// return true 更新组件
// return false 则不更新组件
}
2
3
4
# componentWillUpdate(nextProps,nextState)
shouldComponentUpdate 方法返回 true 后,在组件即将进行重新渲染前调用该函数(注意不要里面去更新 props 或者 state,会导致组件进入死循环),在这之后会调用 render 方法进行重新渲染。
componentWillUpdate(nextProps,nextState) {
// 不要在此处更新props或state
}
2
3
# componentDidUpdate(prevProps,prevState)
组件被重新渲染后该方法会被调用,可以拿到更新前的 props 和 state 。除了首次渲染时调用的componentDidMount,之后每次渲染都会调用该函数。和 componentDidMount 类似的是可以在这里操作更新后的DOM。
componentDidUpdate(prevProps,prevState) {}
# 组件卸载阶段
# componentWillUnmount
该函数在组件卸载前被调用,可以在执行一些清理工作,比如清除组件中使用的定时器或者事件监听器,以避免引起内存泄漏。
componentWillUnmount() {
// 清除定时器或事件监听器
}
2
3
# react16的生命周期
react16的生命周期新引入了三个新的生命周期函数:getDerivedStateFromProps,getSnapshotBeforeUpdate,componentDidCatch,弃用的三个生命周期函数:componentWillMount、componentWillReceiveProps,componentWillUpdate。其他的生命周期功能与前面介绍的相同。
# getDerivedStateFromProps(props, state)
该函数在组件挂载阶段和后续更新阶段调用,根据 props 和 state 两个参数,计算出预期的状态改变,返回一个对象表示新的 state进行更新;如果不需要更新,返回 null 即可。该函数用来替代 componentWillReceiveProps。
static getDerivedStateFromProps(props, state) {
//根据props和state计算出预期的状态改变,返回结果会被送给setState
}
2
3
# getSnapshotBeforeUpdate(prevProps, prevState)
该函数在render之后被调用,可以读取但无法使用DOM的时候。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。返回值将作为componentDidUpdate的第三个参数。该函数配合componentDidUpdate, 可以替代componentWillUpdate。
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log('getSnapshotBeforeUpdate');
return 'react16';
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log('snapshot = ', snapshot);
}
2
3
4
5
6
7
8
# static getDerivedStateFromError()
此生命周期会在后代组件抛出错误后被调用。 它将抛出的错误作为参数,并返回一个值以更新 state。
static getDerivedStateFromError(error) {
// 更新 state 使下一次渲染可以显降级 UI
return { hasError: true };
}
2
3
4
# componentDidCatch(error,info)
任何一处的javascript会触发该函数。
componentDidCatch(error, info) {
// 获取到javascript错误
}
2
3
# 总结
react16更新后的生命周期可以总结为:
# 组件挂载阶段
- constructor
- getDerivedStateFromProps
- render
- componentDidMount
# 组件更新阶段
- getDerivedStateFromProps
- shouldComponentUpdate
- render
- getSnapshotBeforeUpdate
- componentDidUpdate
# 组件卸载阶段
- componentWillUnmount
- 图片来自http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
参考链接: