React 类组件生命周期

目录

1.初始化

componentWillMount  ---  已弃用[a]

render

componentDidMount

2.运行中

componentWillReceiveProps(nextProps)  ---  已弃用[a]

shouldComponentUpdate(nextProps,nextState)

componentWillUpdate  ---  已弃用[b]

render

componentDidUpdate

3.销毁

componentWillUnmount

[1][2]

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.propsthis.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.propsthis.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也需要花时间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值