React生命周期图
React的生命周期从广义上分为以下三个阶段(挂载、渲染、卸载):
- Mounting:已插入真实 DOM
- Updating:正在被重新渲染
- Unmounting:已移出真实 DOM
挂载卸载过程
- constructor() :完成了React数据的初始化,它接受两个参数:props和context,当想在函数内部使用这两个参数时,需使用super()传入这两个参数。 注意:只要使用了constructor()就必须写super(),否则会导致this指向错误。
- componentWillMount :代表的过程是组件已经经历了constructor()初始化数据后,但是还未渲染DOM时。
- componentDidMount:在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。
- componentWillUnmount:在组件从 DOM 中移除之前立刻被调用。(具体包括:clear你在组建中所有的setTimeout,setInterval;移除所有组建中的监听 removeEventListener)
更新过程
- componentWillReceiveProps (nextProps) :在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。
- shouldComponentUpdate(nextProps,nextState) :返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。可以在你确认不需要更新组件时使用。
- componentWillUpdate (nextProps,nextState) :在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。
- componentDidUpdate(prevProps,prevState) :在组件完成更新后立即调用。在初始化时不会被调用。
- render() :会插入jsx生成的dom结构,react会生成一份虚拟dom树,在每一次组件更新时,在此react会通过其diff算法比较更新前后的新旧DOM树,比较以后,找到最小的有差异的DOM节点,并重新渲染。
React新增的生命周期(16.4)
-
getDerivedStateFromProps(nextProps, prevState) :代替componentWillReceiveProps。
旧的React中componentWillReceiveProps方法是用来判断前后两个 props 是否相同,如果不同,则将新的 props 更新到相应的 state 上去。在这个过程中我们实际上是可以访问到当前props的,这样我们可能会对this.props做一些奇奇怪怪的操作,很可能会破坏 state 数据的单一数据源,导致组件状态变得不可预测。
而在 getDerivedStateFromProps 中禁止了组件去访问 this.props,强制让开发者去比较 nextProps 与 prevState 中的值,以确保当开发者用到 getDerivedStateFromProps 这个生命周期函数时,就是在根据当前的 props 来更新组件的 state,而不是去访问this.props并做其他一些让组件自身状态变得更加不可预测的事情。
-
getSnapshotBeforeUpdate(prevProps, prevState) :代替componentWillUpdate。
在 React 开启异步渲染模式后,在执行函数时读到的 DOM 元素状态并不总是渲染时相同,这就导致在 componentDidUpdate 中使用 componentWillUpdate 中读取到的 DOM 元素状态是不安全的,因为这时的值很有可能已经失效了。
而getSnapshotBeforeUpdate 会在最终的 render 之前被调用,也就是说在 getSnapshotBeforeUpdate 中读取到的 DOM 元素状态是可以保证与componentDidUpdate 中一致的。