组件生命周期:组件从被创建到挂载到页面中运行,再到组件不用时卸载的过程。
钩子函数,使开发者的代码可以在固定阶段执行。
注意:只有类组件才有生命周期。函数组件每次都是重新运行函数,旧的组件即刻被销毁。
React组件的生命周期
组件的生命周期主要包括三阶段
- 挂载阶段
- 更新阶段
- 卸载阶段
挂载阶段:组件被创建,执行初始化,并被挂载到DOM中,完成组件的第一次渲染(已经插入真实DOM)
更新阶段:组件被挂载到DOM之后,props和state都可以引起组件的更新(重新渲染)
卸载阶段:在组件被卸载前调用(已经移出真实DOM)
constructor()
ES6中class的构造方法,组件被创建时会首先调用组件的构造方法
初始化state,以及为事件处理程序绑定this
componentWillMount() 不建议使用,已经废用了,是在组件被挂载在DOM之前调用,而且只会被调用一次
render()
根据组件的props和state返回一个React元素
渲染UI
注意:在render()里面不能调用setState()
实际上是调用React.creatElement()
componentDidMount()
在组件被挂载在DOM之后调用,而且只会被调用一次。
可以调用 setState()
向服务器端发送网络请求,以及处理依赖DOM节点的操作
- 父组件调用
render方法- 组件调用
this.setState
componentWillReceiveProps()
props引起的组件更新过程中被调用state引起的组件更新并不会触发该方法的执行shouldComponentUpdate()
用于决定组件是否继续执行更新过程,默认值为true
可以用来减少组件不必要的渲染,从而优化组件的性能
对比前后两个props和state是否相同
componentWillUpdate()
组件初始化时不调用
只有在组件将要更新时才调用,此时可以修改state
render()
根据组件的props和state返回一个React元素
渲染UI
注意:在render()里面不能调用setState()
实际上是调用React.creatElement()
componentDidUpdate()
componentWillUnmount()
componentDidCatch(error, errorInfo)在子组件发生错误是被调用。
error和errorInfo两个参数, error 表示抛出的错误errorInfo 带有 componentStack key 的对象,其中包含有关组件引发错误的栈信息简记,容易记住的生命周期方法
单组件初始化
constructor -> componentWillMount -> render -> componentDidMount
常用 constructor -> render -> componentDidMount
单组件更新state
shouldComponentUpdate -> componentWillUpdate -> render -> componentDidUpdate单组件卸载
componentWillUnmount父子组件初始化
父组件constructor -> 父组件componentWillMount -> 父组件render -> 子组件constructor -> 子组件componentWillMount -> 子组件render -> 子组件componentDidMount -> 父组件componentDidMount父组件更新state
父组件shouldComponentUpdate -> 父组件componentWillUpdate -> 父组件render -> 子组件componentWillReceiveProps -> 子组件shouldComponentUpdate -> 子组件componentWillUpdate -> 子组件render -> 子组件componentDidUpdate -> 父组件componentDidUpdate子组件更新state
子组件shouldComponentUpdate -> 子组件componentWillUpdate -> 子组件render -> 子组件componentDidUpdate父子组件卸载
父组件componentWillUnmount -> 子组件componentWillUnmountReact组件的生命周期(新版)
新版本主要是React 16.3+
新版本的
react生命周期函数主要变化
- 去除了三个不安全函数
componentWillMount、componentWillReceiveProps、componentWillUpdate- 新增了三个生命周期函数
static getDerivedStateFromProps、getSnapshotBeforeUpdate、static getDerivedStateFromError
版本说明
componentWillMount,componentWillReceiveProps,componentWillUpdate 表示使用这些生命周期的代码,有可能在未来的 React 版本中存在缺陷,可能会影响未来的异步渲染。
React 16.3 版本:为不安全的生命周期引入别名 UNSAFE_componentWillMount,UNSAFE_componentWillReceiveProps 和 UNSAFE_componentWillUpdate。(旧的生命周期名称和新的别名都可以在此版本中使用)
React 16.3 之后的版本:为 componentWillMount,componentWillReceiveProps 和 componentWillUpdate 启用弃用警告。(旧的生命周期名称和新的别名都可以在此版本中使用,但旧名称会记录DEV模式警告)
React 17.0 版本:推出新的渲染方式—异步渲染( Async Rendering),提出一种可被打断的生命周期(实际 dom 挂载之前的虚拟 dom 构建阶段),去掉的三个生命周期 componentWillMount,componentWillReceiveProps 和 componentWillUpdate。(从这个版本开始,只有新的“UNSAFE_”生命周期名称将起作用)
constructor -> getDerivedStateFromProps -> render -> componentDidMount
- componentWillMount 不再使用
- getDerivedStateFromProps 替换 componentWillMount
static getDerivedStateFromProps(props, state) 在组件初始化和组件更新时都会被调用
接收state和props两个参数
statenull来表示接收到的props没有变化,不需要更新 state静态方法,所以该生命周期钩子函数内部没有this
将父组件传递过来的props映射到子组件的state上
注意:子组件通过 setState 更新自身状态时,不会改变父组件的 props
getDerivedStateFromProps -> shouldComponentUpdate -> render -> getSnapshotBeforeUpdate -> componentDidUpdate
- 新增 getDerivedStateFromProps
- 替换 componentWillUpdate 为 getSnapshotBeforeUpdate
getSnapshotBeforeUpdate(prevProps, prevState) 在组件更新时被调用。被调用于 render之后、更新 DOM 和 refs 之前。
必须有返回值,返回值将作为 componentDidUpdate 函数方法的第三个参数。
通过this.props和this.state是最新的数据,函数的参数prevProps和prevState是更新前的数据。可以通过比较,做逻辑处理。
componentWillUnmount
无变化
static getDerivedStateFromError(error) 在后代组件抛出错误后被调用。 它将抛出的错误作为参数,并返回一个值以更新 state。
在渲染DOM之前调用,当我们遇到子组件出错的时候可以渲染备用UI,常用作错误边界。
componentDidCatch是在DOM渲染完后才会调用,可以用来输出错误信息或上传一些错误报告。
React 生命周期函数调用顺序单组件初始化
constructor -> getDerivedStateFromProps -> render -> componentDidMount单组件更新state
getDerivedStateFromProps -> shouldComponentUpdate -> render -> getSnapshotBeforeUpdate -> componentDidUpdate单组件卸载
componentWillUnmount父子组件初始化
父组件constructor -> 父组件getDerivedStateFromProps -> 父组件render -> 子组件constructor -> 子组件getDerivedStateFromProps -> 子组件render -> 子组件componentDidMount -> 父组件componentDidMount父组件更新state
父组件getDerivedStateFromProps -> 父组件shouldComponentUpdate -> 父组件render -> 子组件getDerivedStateFromProps -> 子组件shouldComponentUpdate -> 子组件render -> 子组件getSnapshotBeforeUpdate -> 父组件getSnapshotBeforeUpdate -> 子组件componentDidUpdate -> 父组件componentDidUpdate子组件更新state
子组件getDerivedStateFromProps -> 子组件shouldComponentUpdate -> 子组件render -> 子组件getSnapshotBeforeUpdate -> 子组件componentDidUpdate父子组件卸载
父组件componentWillUnmount -> 子组件componentWillUnmountVUE@2组件的生命周期
组件的生命周期
- 初始化阶段
- 编译阶段
- 挂载阶段
- 更新阶段
- 销毁阶段
beforeCreate
在实例初始化之后,进行数据侦听和事件/侦听器的配置之前同步调用。
实例的data和methods等配置还未初始化,无法调用,只能使用一些默认事件。
created
在实例创建完成后被立即同步调用。
实例已完成对选项的处理,意味着以下内容已被配置完毕:数据侦听、计算属性、方法、事件/侦听器的回调函数。
挂载阶段还没开始,且 $el.property 目前尚不可用。
模板还没有编译,不能获取到DOM。
VUE对象是否指定el
VUE对象是否指定template
将编译到render函数中
beforeMounted
挂载开始之前被调用,相关的 render 函数首次被调用。
函数在模板渲染之前调用,也就是DOM节点挂载到真实DOM树之前调用。
此模板进行编译,会调用render函数生成虚拟DOM,同样无法获取DOM节点(此时只存在虚拟DOM,还在JS级别)。
mounted
实例被挂载后调用,这时 el 被新创建的 vm.$el 替换。
注意:mounted不会保证所有的子组件也都被挂载完成。
执行该钩子函数时,模板编译完成,而且挂载到真实DOM树上面去了,也就是页面可以显示了。(该钩子在服务器端渲染期间不被调用)
单组件初始化
单组件更新
单组件卸载
父子组件初始化
父组件更新data,此data没传递给子组件
父组件更新data,此data传递给了子组件
子组件更新data
父子组件卸载
beforeUpdate
在数据发生改变后,DOM 被更新之前被调用。
这里适合在现有 DOM 将要被更新之前访问它,比如移除手动添加的事件监听器。
该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务器端进行。
该钩子函数在data数据发生变化之后调用,data里面的数据已经是最新的了,但是页面上DOM还没有更新最新的数据。
updated
在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用。
当这个钩子被调用时,组件 DOM 已经更新,可以执行依赖于 DOM 的操作。要相应状态改变,通常最好使用计算属性或 watcher 取而代之。
注意,updated 不会保证所有的子组件也都被重新渲染完毕。如果你希望等到整个视图都渲染完毕,可以在 updated 里使用 vm.$nextTick
该钩子函数会在data数据更新之后执行,而且此时页面也渲染更新完成了,显示的就是最新的数据。
注意:不要在updated中修改data数据,很容易造成死循环。
beforeDestroy
实例销毁之前调用。实例仍然完全可用。
在这个钩子函数里面解除一些全局或者自定义事件。
destroyed
实例销毁后调用。
该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。
VUE@2生命周期
{{ message }}
{{ msg }}
errorCaptured
在捕获一个来自后代组件的错误时被调用。
钩子函数的三个参数:错误对象、发生错误的组件实例、一个包含错误来源信息的字符串。
该钩子函数可以返回 false 以阻止该错误继续向上传播。
activated
deactivated
VUE@3组件的生命周期
setup() : 开始创建组件之前,在 beforeCreate 和 created 之前执行,创建的是 data 和 method
onBeforeMount() : 组件挂载到节点上之前执行的函数;
onMounted(): 组件挂载完成后执行的函数;
onBeforeUpdate(): 组件更新之前执行的函数;
onUpdated(): 组件更新完成之后执行的函数;
onBeforeUnmount(): 组件卸载之前执行的函数;
onUnmounted(): 组件卸载完成后执行的函数;
onActivated(): 被包含在中的组件,会多出两个生命周期钩子函数,被激活时执行;
onDeactivated(): 比如从 A 组件,切换到 B 组件,A 组件消失时执行;
onErrorCaptured(): 当捕获一个来自子孙组件的异常时激活钩子函数。
生命周期函数的运行基本顺序是
setup->beforeCreate->created
单组件初始化
setup -> created -> onBeforeMount -> onRenderTracked -> onMounted单组件更新
onRenderTriggered-> onBeforeUpdate -> onUpdated单组件卸载
onBeforeDestroy -> onDestroyed父子组件初始化
父组件更新data,此data没传递给子组件
父组件更新data,此data传递给了子组件
子组件更新data
父子组件卸载
VUE@2与VUE@3对比| vue@2 | vue@3 |
|---|---|
| beforeCreate | setup(()=>{}) |
| created | setup(()=>{}) |
| beforeMount | onBeforeMount(()=>{}) |
| mounted | onMounted(()=>{}) |
| beforeUpdate | onBeforeUpdate(()=>{}) |
| updated | onUpdated(()=>{}) |
| beforeDestroy | onBeforeUnmount(()=>{}) |
| destroyed | onUnmounted(()=>{}) |
| activated | onActivated(()=>{}) |
| deactivated | onDeactivated(()=>{}) |
| errorCaptured | onErrorCaptured(()=>{}) |
Vue@2和Vue@3钩子变化不大,使用setup()钩子来替代 beforeCreate、created 两个钩子函数。
VUE与React生命周期对比对比的目的在于处理相同与不同
Vue、React 生命周期函数基本类似,组件的创建、更新、卸载都有对应的函数方法调用。
单组件、父子组件渲染类似。
参数比较:
Vue生命周期函数除了 errorCaptured 都是没有参数的。React生命周期函数都有参数并且能访问到旧的或新的props和state。组件更新
React父组件更新,子组件一定都会更新渲染,除非自己手动优化(继承PureComponent或者实现shouldComponent方法)。Vue中除非子组件依赖父组件的数据改变了,否则子组件是不会重新渲染的。组件更新处理
Vue 数据改变就一定会重新渲染,无法阻止。React 能通过 shouldComponent 方法来决定是否需要渲染。错误处理
Vue 在组件报错的时候页面还是会渲染,只是引发出错的地方可能数值不对。React 组件报错的时候会导致页面空白,编译报错将提示信息到浏览器(getDerivedStateFromError 做边界处理)。生命周期影响
React的生命周期函数,大多都在处理当前的props与stateVUE相比较多了缓存的生命周期函数 activated、deactivated 和用于开发调试的renderTracked、renderTriggered生命周期函数。