React生命周期及其生命周期性能优化详解

600 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情

一、React组件从初始化到销毁阶段所经历的生命周期

1.初始化阶段

  • componentWillMount:render之前最后一次修改状态的机会
  • render:只能访问this.props和this.state,不允许修改状态和DOM输出
  • componentDidMount:成功render并渲染完成真实DOM之后触发,可以修改DOM

2.运行中阶段

  • componentWillReceiveProps:父组件修改属性触发
  • shouldComponentUpdate:返回false会阻止render调用
  • componentWillUpdate:不能修改属性和状态
  • render:只能访问this.props和this.state,不允许修改状态和DOM输出
  • componentDidUpdate:可以修改DOM

3.销毁阶段

  • componentWillUnmount:在删除组件之前进行清理操作,比如定时器和事件监听器

二、React重要生命周期详解

1.componentDidUpdate

componentDidUpdate(prevProps,prevState){
    prevProps // 旧状态
    prevState // 新状态
}

2.shouldComponentUpdate

scu提示符,阻止不必要的渲染及DOM节点Diff算法对比,提升性能

 shouldComponentUpdate(nextProps,nextState){
    // return true;// 应该更新
    // return false; // 阻止更新
    this.state // 老状态
    nextState // 新状态
    if(JSON.stringify(this.state)!==JSON.stringify(nextState)){
        return true
    }
    return false
 }

3.componentWillReceiveProps

父组件修改属性更改状态才会触发

componentWillReceiveProps(nextProps){
    // 拿到父组件传来的最新属性
    // 可以把属性转为自己内部状态
}

4.老生命周期的问题

(1)componentWillMount,在ssr中这个方法会被多次调用(Fiber算法,优先级问题,可能会被多次停止,重新执行),所以会触发多遍,同时在这里如果绑定事件,将无法解绑,导致内存泄漏,变得不够安全高效逐步废弃,UNSAFE_componentWillMount可以屏蔽控制台警告
(2)componentWillReceiveProps外部组件多次频繁更新传入多次不同的Props,会导致不必要的异步请求
(3)componentWillUpdate,更新前记录DOM状态,可能会做一些处理,与componentDidUpdate相隔时间过长会导致状态不可信

5.新生命周期的替代

(1)getDerivedStateFromProps第一次的初始化组件以及后续的更新过程中(包括自身状态更新以及父传子),返回一个对象作为新的state,返回null说明不需要在这里更新state

// 老生命周期写法
componentDidMount(){
    if(this.props.value!==undefined){
        this.setState({
            current:this.props.value
          })
    }
}
componentWillReceiveProps(nextProps){
    if(nextProps.value!==undefined){
      this.setState({
            current:nextProps.value
          })  
    }
}
// 新的生命周期写法
static getDerivedStateFromProps(nextProps,nextState)
 if(nextProps.value!==undefined){
      return {
            current:nextProps.value
          }) 
    }
}

(2)getSnapShotBeforeUpdate取代了conmponentWillUpdate,触发时间为update发生的时候,在render之后Dom渲染之前返回一个值,作为componentDidUpdate的第三个参数

    // 获取新数据插入前,页面滚动高度
    getSnapShotBeforeUpdate(){
        return this.refs.wrapper.scrollHeight
    }
    componentDidUpdate(prevProps,prevState,preHeight){
        this.refs.wrapper.scroolTop+=this.refs.wrapper.scrollHeight-preHeight
    }

三、React利用生命周期做性能优化

1.shouldComponentUpdate

 控制组件自身或者子组件是否需要更新,尤其在子组件非常多的情况下需要优化。

2.PureComponent

PureComponent会帮你比较新props和旧props,新的state和旧的state(值相等或者对象含有相同属性、且属性值相等),决定shouldComponentUpdate返回true或者false,从而决定要不要呼叫render function 注意: 如果你的state或props永远都会变,那PureComponent并不会比较快,因为shallowEqual也需要花时间。

import React,{PureComponent} from 'react'
export default class APP extends PureComponent{
    render(){
        return ()
    }
 }