目录
熟练使用react开发项目之后,最近在学习react的底层原理以及源码,顺便总结一下react的生命周期。
一、什么是react?
在学习原理和源码之前我们必须先明白什么是react。官方文档对于react的定义是:
A JavaScript library for building user interfaces
用于构建用户界面的 JavaScript 库
其实我们可以简单的理解为react主要做两件事:响应事件、渲染UI
二、react的生命周期
在学习react的生命周期函数之前我们先来简单的了解一下react的渲染过程:
首屏渲染过程如下:
- 调用ReactDOM.render
- 进入Render阶段
- 采用深度优先遍历创建fiber树(虚拟dom节点)
- 进入commit阶段,即进入渲染器渲染视图
组件更新阶段的过程:
- 进入Render阶段
- 采用深度优先遍历的方式创建fiber树
- 通过diff算法标记变化
- 进入commit阶段,执行变化对应的视图操作
由以上的过程描述我们可以把react的生命周期分为两个阶段:render阶段和commit阶段
接下来我们就来了解一下render阶段和commit阶段,页面挂载、组件更新以及组件卸载时分别涉及的钩子函数以及各个钩子函数的作用:
旧的生命周期(v16.3之前):
Mount | Update | Unmount | |
render阶段 | constructor 加载的时候调用一次,可以初始化state → componentWillMount 组件加载时调用,整个生命周期只调用一次,此时可以修改state → render 创建虚拟dom,进行diff算法,更新dom树 | props更新时会触发componentWillReceiveProps 组件接收新的props时调用 → shouldComponentUpdate 组件接收新的prop或者state时调用,返回true则会更新dom,返回false则阻止更新 → componentWillUpdate 组件将要更新时调用,可以修改state → render 创建虚拟dom,进行diff算法,更新dom树 | |
commit阶段 | componentDidMount 组件渲染之后调用,只调用一次,可获取真实dom节点 | componentDidUpdate 组件更新完后调用 | componentWillUnmount 组件即将卸载前调用 |
新的生命周期(v16.3开始):
Mount | Update | Unmount | |
render阶段 | constructor 加载的时候调用一次,可以初始化state → getDerivedStateFromProps(props,state) 用来替换componentWillReceiveProps()更为安全的方案。不能使用this,返回一个取决于props变化的对象用来更新state,返回null则不需要更新state,解决在某些特殊情况下state的值取决于props的问题。 → render 创建虚拟dom,进行diff算法,更新dom树 | getDerivedStateFromProps 同左边 → shouldComponentUpdate 组件接收新的prop或者state时调用,返回true则会更新dom,返回false则阻止更新 → render 创建虚拟dom,进行diff算法,更新dom树 | |
pre-commit阶段 | getSnapshotBeforeUpdate 用来替换componentWillUpdate()更为安全的方案。在更新之前被调用,返回的值会传给componentDidUpdate(),常用于在异步渲染期间改变窗口尺寸等 | ||
commit阶段 | componentDidMount 组件渲染之后调用,只调用一次,可获取真实dom节点 | componentDidUpdate 组件更新完后调用 | componentWillUnmount 组件即将卸载前调用 |
总结:如上描述可知在16.x之前和之后的生命周期函数的变化有,16.x的生命周期弃用了componentWillMount、componentWillReceiceProps、componentWillUpdate
新增了getDerivedStateFromProps、getSnapshotBeforeUpdate来代替以上弃用的三个钩子函数。在react16的版本中并未完全删除这三个生命周期函数,而是新增UNSAFE_前缀去使用(UNSAFE_componentWillMount等),废弃的钩子和新增的钩子函数同时使用会报错,但是在react17中则弃用的钩子函数将被删除。
三、对于react生命周期的思考
其实react生命周期过程没有改变,只是16.3的版本加入fiber之后,将以前的同步渲染改成了异步渲染,因此对应生命周期函数的处理方式也改变了。