React 生命周期
旧生命周期
挂载
-
constructor
-
componentWillMount
-
render
-
componentDidMount
更新
props
- componentWillRecieveProps(nextProps)
根据最新的 props 来设置 state,返回的 state 会和已有的 state 进行合并,这个生命周期中不会二次更新
- shouldComponentUpdate(nextProps, nextState)
用来进行性能优化,不要在这个生命周期中 setState,会导致死循坏
- componentWillUpdate(nextProps, nextState)
组件更新之前调用,这个时候页面还没有被更新,所以我们可以获取更新前的 DOM 相关信息,不要再这个生命周期中设置 state,会导致死循环
- render
不要再这个方法中设置 state,会导致死循环
- componentDidUpdate(prevProps, prevState)
组件完成了渲染,此时页面已经更新,prevProps 和 prevState 表示的是之前的状态
state
-
shouldComponentUpdate
-
componentWillUpdate
-
render
-
componentDidUpdate
卸载
- componentWillUnmount
注意:setState 是同步的,但是为什么我们在 React 中的生命周期函数/事件处理中不能在 setState 之后立即获取到最新的 state 呢;原因是 React 对于 state 的更新做了优化,将多次的 state 更新合并成了一次,但是在定时器/通过 addEventListener 来添加的事件处理函数中 setState 时,React 会立即更新 state
React 新的生命周期
挂载时
-
constructor
-
static getDerivedStateFromProps(nextProps, prevState)
-
render
-
更新 DOM & refs
-
componentDidMount
更新时
props/state 更新
-
static getDerivedStateFromProps
-
shouldComponentUpdate
-
render
-
getSnapshotBeforeUpdate(nextProps, prevState)
-
更新 DOM&refs
-
componentDidUpdate
forceUpdate()
-
render
-
getSnapshotBeforeUpdate(nextProps, prevState)
-
更新 DOM&refs
-
componentDidUpdate(prevProps, prevState, snapshot)
卸载时
- componentWillUnmount
新旧生命周期的对比
废弃了三个生命周期componentWillMount
、componentWillRecieveProps
、componentWillUpdate
新增了两个生命周期static getDerivedStateFromProps
、getSnapshotBeforeUpdate
废弃那三个生命周期的原因
在旧版本的 React 中,组件的更新是同步的,所以主线程会被占用较长的时间,可能会导致浏览器掉帧,表现出来的就是页面出现卡顿。为了解决这个问题,引入了 React Fiber
React Fiber 机制:组件更新是可以被中断的,利用浏览器的 requestIdleCallback 方法,将可中断的任务进行分片处理,每一片运行的时间很短,不会占用主线程太长时间
在浏览器的每一帧中预留时间给 JS 线程,React 利用这些时间来更新组件,在源码中预留的时间是 5ms
当预留的时间够了时,就将控制权交给浏览器渲染 UI,React 则等下一帧时间到来的时候再继续更新组件
因为 React Fiber 的 reconcilation 这个过程是可以中断然后在空闲时继续执行,所以就会导致挂载和更新之前的钩子都有可能执行多次或者是不执行。所以 React 用下面两个钩子来代替
- static getDerivedStateFromProps(nextProps, prevState)
组件第一次挂载和更新的时候都会被调用,返回的对象会和 state 进行合并,用于在 props 改变的时候来更新 state;返回 null 的时候则不更新任何内容。可以用来代替componentWillMount
和 componentWillRecieveProps
- getSnapshotBeforeUpdate(nextProps, nextState)
在 render 调用之后,实际 DOM 渲染之前,在这个阶段我们可以拿到上一个状态 DOM 元素元素的坐标和大小等相关信息。可以用来代替 componentWillUpdate 生命周期,该生命周期的返回值可以作为 componentDidUpdate 的第三个参数出现
父子组件生命周期的执行顺序
-
子组件自身的状态发生改变且不影响父组件的情况下,只会触发子组件本身的生命周期函数
-
父组件的状态发生变化,包括子组件的挂载和卸载,会触发自身的生命周期以及子组件的更新
-
render 之前包括 render 的生命周期函数都是父组件先执行然后子组件再执行
-
render 之后的生命周期都是子组件先执行然后父组件再执行且是交替执行
-
当子组件卸载的时候会触发父组件的更新以及子组件本身的 componentWillUnmount 生命周期函数(仅触发子组件的这一个生命周期函数)
-
子组件卸载
-
Parent: getDerivedStateFromProps
-
Parent: shouldComponentUpate
-
Parent: render
-
Parent: getSnapshotBeforeUpdate
-
Child: componentWillUnmount
-
Parent: componentDidUpdate
-
-
子组件再次挂载
-
Parent: getDerivedStateFromProps
-
Parent: shouldComponentUpdate
-
Parent: render
-
Child: constructor
-
Child: getDerivedStateFromProps
-
Child: render
-
Parent: getSnapshotBeforeUpdate
-
Child: componentDidMount
-
Parent: componentDidUpdate
-
网友评论