生命周期

本文共--字 阅读约--分钟 | 浏览: -- Last Updated: 2021-05-26

React组件的生命周期

// 生命周期函数
// 组件创建阶段 只执行一次
componentWillMount(){}
render(){}
componentDidMount(){}

// 组件运行阶段 根据状态的改变触发0或多次
componentWillReceiveProps(){}
shouldComponentUpdate(){}
componentWillUpdate(){}
render(){}
componentDidUpdate(){}

// 组件销毁阶段 只执行一次
componentWillUnmount(){}

流程

  • 1.创建时期,第一个执行的函数是constructor(),定义state
  • 2.组件挂载之前触发componentWillMount,此时页面还未渲染。
  • 3.执行render函数,创建虚拟dom,将虚拟dom挂载到真实dom上去
  • 4.完成挂载时,触发componentDidMount函数,页面已经被渲染。
  • 5.1 如果属性(props)改变,接受的传参改变了,触发componentWillReceiveProps函数,然后触发shouldComponentUpdate函数
  • 5.2 如果状态(state)改变,直接触发shouldComponentUpdate函数
  • 6.1shouldComponentUpdate函数如果return false 重新回到运行中的状态,页面没有任何更新
  • 6.2shouldComponentUpdate函数如果return true 即代表页面即将发生更新,继续走下面的流程,不定义默认返回true
  • 7.组件更新前,触发componentWillUpdate函数。
  • 8.执行render函数,比较更新虚拟dom,重新渲染页面
  • 9.组件完成更新后,触发componentDidUpdate函数
  • 10.组件被销毁之前触发componentWillUnmount函数,调用ReactDOM.unmountComponentAtNode(document.getElementById('app'))可以销毁一个组件。

注意

  • 1.this.forceUpdate()强制刷新会跳过shouldComponentUpdate钩子函数
  • 2.父组件只要调用setState函数 子组件也会更新 不管子组件有没有使用到父组件中的数据 但是可以在子组件中的shouldComponentUpdate进行拦截
  • 3.因为父组件状态改变了 如果没有在shouldComponentUpdate中比较拦截 就会走下面的流程 必然会再次触发render函数
  • 4.触发了render函数 子组件就会触发更新 componentWillReceiveProps钩子就会触发
  • 5.PureComponent可以避免这一点,如果子组件都没有用到父组件中的数据 那么子组件比对state必然没有改变
  • 6.不要在shouldComponentUpdate、componentWillUpdate、render、componentDidUpdate函数中调用setState就会造成死循环

PureComponent

根组件在setState的时候会触发render函数,也会同时触发所有组件的更新,这是不愿意看到的,也会影响性能。

父组件有时候的更新状态是希望子组件更新的,有时候是不希望的(没有修改影响子组件的状态的时候,所以需要在shouldComponentUpdate中具体分析。

class myCom extends React.PureComponent {

}

// PureComponent 与 Component 的差异 体现在shouldComponentUpdate上
// PureComponent 会将nextState 和 nextProps (shouldComponentUpdate的参数)
// 与当前的 state 和 props 去比较 如果不同 则返回true 如果相同就返回false 
// 而Component的 shouldComponentUpdate 默认返回true

// 但是 PureComponent 也只比较 state 和 props 的第一层直系属性
// 因为使用state定义了一个嵌套很深的json 此时一层层去比较就会太浪费性能