目录
componentWillReceiveProps(nextProps) --- 已弃用[a]
shouldComponentUpdate(nextProps,nextState)
componentWillUpdate --- 已弃用[b]
static getDerivedStateFromProps(prevProps,prevState) --- [1]
getSnapshotBeforeUpdate --- [2]
注意这里是类组件的生命周期;函数式组件只有属性的概念,16.8之后借助hooks实现类似的功能
React类组件生命周期又以16.2为节点,16.2之后React更新了diff算法,所以加入了新的生命周期函数写法。不再推荐使用的生命周期函数,使用时要加前缀,示例:UNSAFE_xxx
分为三个阶段:初始化、运行中、销毁
constructor其实是类初始化必走的一个函数,有些资料也把它规定为一个生命周期。
生命周期函数会被react自动调用
constructor(props)
1.初始化
componentWillMount --- 已弃用[a]
render
componentDidMount
2.运行中
componentWillReceiveProps --- 已弃用[a]
shouldComponentUpdate
componentWillUpdate --- 已弃用[b]
render
componentDidUpdate
3.销毁
componentWillUnmount
4.错误处理
static getDerivedStateFromError(err) --- 不常用
componentDidCatch(err,info) --- 常用做记录log
[a]现在被static getDerivedStateFromProps[1]替代
[b]被getSnapshotBeforeUpdate[2]替代,[2]的执行时机在render后
详细介绍:(可以使用目录直接跳转)
1.初始化
除了render函数,其它函数在后续阶段均不再执行
componentWillMount --- 已弃用[a]
render之前最后一次修改状态的机会---对状态进行逻辑计算,初始化数据的作用
render
只能访问 this.props 和 this.state ,不允许修改状态(死循环,栈溢出)和DOM输出
componentDidMount
成功render并渲染完成真实DOM之后触发,可以修改DOM---推荐把axios放在这里;
订阅函数的调用;
定时器,如setInterval;
基于创建完的dom进行初始化,betterscroll初始化
2.运行中
componentWillReceiveProps(nextProps) --- 已弃用[a]
条件:必须构成父子关系。
父组件只要触发自己的更新机制(比如调用setState,不一定要给子组件传属性),子组件的componentWillReceiveProps就会被调用
也算react的一个痛点。只要顶层组件更新,它引用过的孩子组件都会更新。
这也可以解释vue中父子组建生命周期执行顺序的原因了
该函数中 this.props 拿到的属性是旧的属性,形参传来的属性才是要更新的属性值
意义在于:可以最先获取父组件传来的属性,可以把属性转化成孩子自己的状态,对状态进行处理加工,再进行渲染。
shouldComponentUpdate(nextProps,nextState)
性能优化函数
直接释意为:组件应该更新吗?---返回false会阻止render调用
只要调用了setState,不管设置的值有没有改变,仍然需要对比虚拟dom,此时更新的生命周期白白又走了一遍,而react中最浪费性能的恰巧也是虚拟dom的对比。这个时候可以返回false阻止更新
它会在组件接收到新的 props 或者 state,且即将执行重新渲染(render 方法)之前被调用。
如果需要对比的属性过多,可以把它们转换为字符串对比。(不能转换为对象,因为对象永远是不相等的)
shouldComponentUpdate(nextProps, nextState) {
if(JSON.stringify(this.state) !== JSON.stringify(nextState)) {
return true;
}
return false;
}
componentWillUpdate --- 已弃用[b]
此处不能修改属性和状态
执行时机:
1. 组件收到新 props/state 后
2. render 执行之前
3. 还未触发 DOM 更新(DOM 仍为「更新前状态」)
render
只能访问 this.props 和 this.state ,不允许修改状态和DOM输出
componentDidUpdate
更新后,想要获取dom节点;可以修改DOM;依赖于dom操作的库。
缺点,会执行多次
3.销毁
componentWillUnmount
在删除组件之前进行清理操作,比如计时器和事件监听
因为绑在windows窗口上的事件并不会随着组件销毁而销毁
componentWillUnmount() {
// 清除定时器
clearInterval(this.timer);
// 移除事件监听
window.removeEventListener('resize', this.handleResize);
}
[1][2]
static getDerivedStateFromProps(prevProps,prevState) --- [1]
(从属性中获取衍生的状态)
执行时机:第一次的初始化组件以及后续的更新过程中 (包括自身状态更新以及父传子,所以几乎除了销毁都在执行该函数),
返回一个对象作为新的state,返回null则说明不需要在这里更新state
它是一个类的方法,不能在里面发ajax请求,要配合componentDidUpdate使用
之前的UNSAFE_componentWillReceiveProps中的异步请求如果被打断了就要重新再执行一遍,发多次请求,造成性能损耗。
而getDerivedStateFromProps虽然也会触发多次,但最终在事件循环结束后返回的return要和老的state合并,然后再componentDidUpdate中拿到更新后的状态值,发一次ajax请求。
state = {
myname:"kerwin",
myage:100
}
static getDerivedStateFromProps(nextProps,nextState){
//不能写this.state是因为state是静态的,是类属性
console.log("getDerivedStateFromProps")
return {
myname:nextState.myname.sbstring(0,1).toUpperCase()+nextState.myname.substring(1)
}
}
getSnapshotBeforeUpdate --- [2]
该函数必须要return一些东西。
在render之后dom渲染之前返回一个值,这个值被当做componentDidUpdate的第三个参数
执行时机:
1. render 执行之后
2. DOM 更新之前(即 React 计算出 DOM 变更但尚未应用到页面)
3. 组件实例仍存在(可访问 this)
之前存在的问题:
willUpdate存在过渡render,如果在render或didUpdate中存在其它异步操作,或者期间滚动条移动,就会造成willUpdate中记录的高度不准确。
解决:getSnapshotBeforeUpdate在render之后didUpdate之前执行,记录的数据很准
说白了这个生命周期就是能确保获取到了最新的dom后再执行
补充内容
一、为什么一些旧的生命周期不安全呢?
此处以componentWillMount()举例
16.2的时候,react推出了fiber技术(意为"纤维",比线程更小的)。数据量大时,虚拟dom的对比(同步)会占用线程,造成浏览器"假死"现象,所以fiber优化了diff算法,把"创建dom"到"组件渲染"的整个过程拆分为无数个小的分片任务来执行(异步)。
过程中高优先级的任务优先执行,低优先级:willMount中找哪些节点将被挂载,高优先级:render正在渲染、DidMount已经渲染完。所以willMount的执行容易被打断,造成执行多次不够安全的风险
所以,旧的生命周期存在的问题:
1 componentWillMount,在ssr中 这个方法会被多次调用,所以会重复触发多遍,同时在这里如果绑定事件,将无法解绑,导致内存泄漏,变得不够安全高效逐步废弃
2 componentWillReceiveProps,外部组件多次频繁更新传入多次不同的props,会导致不必要的异步请求
3 componentWillUpdate,更新前记录dom状态,可能会做一些处理,与componentDidUpdate相隔时间过长,会导致状态不可信
二、react中性能优化的方案:(这里简单概括)
1.shouldComponentUpdate
控制组件自身或者子组件是否需要更新,尤其在子组件非常多的情况下,需要进行优化
2.PureComponent
PureComponent会帮你 比较新props 和 旧的props,新的state和老的state(值相等,或者对象含有相同的属性、且属性值相等),决定shouldcomponentUpdate 返回true 或者false,从而决定要不要呼叫render function
注意:
如果你的state 或props [永远都会变],那PureComponent 并不会比较快,因为shallowEqual也需要花时间

被折叠的 条评论
为什么被折叠?



