React的生命周期(类组件)
生命周期: 组件从诞生到销毁会经历一系列的过程, 这个过程就叫做生命周期, React在组件的生命周期中提供了一系列的钩子函数(类似于事件), 开发者可以在这些事件中注入代码, 这些事件会在合适的时机运行。
旧版本生命周期(React < 16.0.0>)
constructor
初始化阶段, 初始化属性和状态
- 构造函数, 同一个组件对象只会创建一次, 不会反复创建
- 不能在第一次挂载到页面之前调用setState, 那么也就意味着在constructor中严禁使用setState
componentWillMount
组件即将挂载到页面
- 和构造函数一样, 正常情况下componentWillMount只会运行一次
- 使用setState不会报错, 但是为了避免bug, 笔者建议仍然不要在该钩子函数中使用setState, 原因是因为该函数在某些情况下可能被调用多次
render
组件渲染虚拟dom
- 返回的react元素会被挂载到虚拟dom树中, 最终会被渲染到真实的dom中
- render可能不止运行一次, 只要需要重新渲染就会重新运行
- render中严禁调用setState, 会导致无限递归渲染
componentDidMount
组件已经挂载完毕(虚拟DOM已经挂载到页面成为真实dom)
- componentDidMount只会执行一次
- 通常情况下, 会将网络请求, 启动计时器等一系列页面
- 在componentDidMount中可以使用setState
自此之后组件进入活跃状态
componentWillReceiveProps(nextProps)
当组件中的属性发生变化会触发componentsWillReceiveProps
- 即将接收新的属性值
- 参数值nextProps表示新的属性值
- 该函数可能会导致一些bug, 不推荐使用
shouldComponentUpdate(nextProps, nextState)
当组件中的属性发生变化(并且触发componentWillReceiveProps(nextProps)后)或者状态state发生变化会触发shouldComponentUpdate, 表示是否应该重新渲染组件
- 性能优化点
- 指示react是否要重新渲染该组件, 通过返回true和false来指定, 默认情况下返回true
- 指的是属性重新被赋值, 而非属性值一定要发生变化, 也就意味着赋值同样的数据给同一个属性也会触发
- 提供两个参数nextProps, nextState,表示新的属性和新的状态
- 如果写了这个钩子函数, 就必须要提供返回值(true或者false)
componentWillUpdate
组件即将重新渲染
- 个人认为比较鸡肋, 了解一下就好
componentDidUpdate(prevProps, prevState)
组件更新完毕
- 可以得到组件之前的状态和属性, 通过参数prevProps和prevState来获取
- 往往在该函数中使用dom操作改变元素
componentWillUnmount
组件即将被销毁
- 通常在该函数中销毁组件依赖的资源, 比如计时器
在react中书写生命周期函数(类组件)
import React from 'react';
export default class ClassCmp extends React.Component {
constructor(props) {
super(props);
this.state = {
number: 0
}
console.log('constructor', '一个新的组件诞生了');
}
componentWillMount() {
console.log('componentWillMount', '组件即将被挂载');
}
render() {
console.log('render', '组件渲染虚拟dom');
return <div>
<h2>旧版生命周期</h2>
<h2>状态number: {this.state.number}</h2>
<h2>属性number: {this.props.number}</h2>
</div>
}
componentDidMount() {
console.log('componentDidMount', '组件挂载完毕');
}
componentWillReceiveProps(nextProps) {
console.log('componentWillReceiveProps', this.props, nextProps, '组件属性被重新赋值');
}
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate', '组件是否要被重新渲染', this.props, this.state, nextProps, nextState);
// if(this.props.number === nextProps.number && this.state.number === nextState.number) {
// return false
// }
return true;
}
componentWillUpdate() {
console.log('componentWillUpdate', '组件即将被重新渲染');
}
componentDidUpdate(prevProps, prevState) {
console.log('componentDidUpdate', '组件更新完毕', prevProps, prevState);
}
componentWillUnmount() {
console.log('componentWillUnmount', '组件即将被销毁');
}
}
新版生命周期(React > 16.0.0)
React官方认为数据的来源必须是单一的, 同时认为有些生命周期函数容易产生bug, 于是新的生命周期函数诞生了
简而言之, 新版的生命周期函数相较于旧版的移除了componentWillMount, componentRecevieProps和componentWillUpdate, 而在每一次render方法之前添加了一个static getDerivedStateFromProps(nextProps, nextState);在componentDidUpdate之前提供了一个getSnapShotBeforeUpdate
static getDerivedStateFromProps(props, state)
从属性中获取最新的动态
- 通过参数可以获取新的属性和状态
- 在每次render之前一定会走一次, 也就意味着constructor之后该函数在render之前也会运行一次
- 该函数是静态的
- 函数的返回值会覆盖掉组件状态
- 该函数几乎不怎么用
getSnapShotBeforeUpdate
真实的dom已经构建完毕, 但是还未实际渲染到页面中
- 该函数通常用于实现一些附加的dom操作
- 该函数的返回值会作为componentDidMount的第三个参数