React与Vue组件生命周期以及钩子函数
组件生命周期
组件生命周期:组件从被创建到挂载到页面中运行,再到组件不用时卸载的过程。
-
钩子函数,使开发者的代码可以在固定阶段执行。
-
注意:只有类组件才有生命周期。函数组件每次都是重新运行函数,旧的组件即刻被销毁。
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的对象,其中包含有关组件引发错误的栈信息
- 接收
React 生命周期函数调用顺序
简记,容易记住的生命周期方法
单个组件生命周期函数调用顺序
-
单组件初始化
-
constructor->componentWillMount->render->componentDidMount -
常用
constructor->render->componentDidMount
-
-
单组件更新
stateshouldComponentUpdate->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->子组件componentWillUnmount
React组件的生命周期(新版)

新版本主要是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两个参数- 可以通过返回一个对象来更新组件自身的
state - 返回
null来表示接收到的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
-
单组件更新
stategetDerivedStateFromProps->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->子组件componentWillUnmount
VUE@2组件的生命周期

组件的生命周期
- 初始化阶段
- 编译阶段
- 挂载阶段
- 更新阶段
- 销毁阶段
初始化阶段
-
beforeCreate
-
在实例初始化之后,进行数据侦听和事件/侦听器的配置之前同步调用。
-
实例的
data和methods等配置还未初始化,无法调用,只能使用一些默认事件。
-
-
created
-
在实例创建完成后被立即同步调用。
-
实例已完成对选项的处理,意味着以下内容已被配置完毕:数据侦听、计算属性、方法、事件/侦听器的回调函数。
-
挂载阶段还没开始,且 $el.property 目前尚不可用。
-
模板还没有编译,不能获取到DOM。
-
编译阶段
-
VUE对象是否指定
el -
VUE对象是否指定
template -
将
<template>编译到render函数中
挂载阶段
-
beforeMounted
-
挂载开始之前被调用,相关的 render 函数首次被调用。
-
函数在模板渲染之前调用,也就是DOM节点挂载到真实DOM树之前调用。
-
此模板进行编译,会调用
render函数生成虚拟DOM,同样无法获取DOM节点(此时只存在虚拟DOM,还在JS级别)。
-
-
mounted
-
实例被挂载后调用,这时 el 被新创建的 vm.$el 替换。
-
注意:
mounted不会保证所有的子组件也都被挂载完成。- 如果你希望等到整个视图都渲染完毕再执行某些操作,可以在 mounted 内部使用 vm.$nextTick
-
执行该钩子函数时,模板编译完成,而且挂载到真实DOM树上面去了,也就是页面可以显示了。(该钩子在服务器端渲染期间不被调用)
-
生命周期组件调用顺序
单组件
-
单组件初始化
- beforeCreate -> created -> beforeMount -> mounted
-
单组件更新
- beforeUpdate -> updated
-
单组件卸载
- beforeDestroy -> destroyed
父子组件
-
父子组件初始化
- 父组件beforeCreate -> 父组件created -> 父组件beforeMount -> 子组件beforeCreate -> 子组件created -> 子组件beforeMount -> 子组件mounted -> 父组件mounted
-
父组件更新data,此data没传递给子组件
- 父组件beforeUpdate -> 父组件updated
-
父组件更新data,此data传递给了子组件
- 父组件beforeUpdate -> 子组件beforeUpdate -> 子组件updated -> 父组件updated
-
子组件更新data
- 子组件beforeUpdate -> 子组件updated
-
父子组件卸载
- 父组件beforeDestroy -> 子组件beforeDestroy -> 子组件destroyed -> 父组件destroyed
更新阶段
-
beforeUpdate
-
在数据发生改变后,DOM 被更新之前被调用。
-
这里适合在现有 DOM 将要被更新之前访问它,比如移除手动添加的事件监听器。
-
该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务器端进行。
-
该钩子函数在data数据发生变化之后调用,
data里面的数据已经是最新的了,但是页面上DOM还没有更新最新的数据。
-
-
updated
-
在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用。
-
当这个钩子被调用时,组件 DOM 已经更新,可以执行依赖于 DOM 的操作。要相应状态改变,通常最好使用计算属性或 watcher 取而代之。
-
注意,updated 不会保证所有的子组件也都被重新渲染完毕。如果你希望等到整个视图都渲染完毕,可以在 updated 里使用 vm.$nextTick
-
该钩子函数会在data数据更新之后执行,而且此时页面也渲染更新完成了,显示的就是最新的数据。
-
注意:不要在
updated中修改data数据,很容易造成死循环。
-
销毁阶段
-
beforeDestroy
-
实例销毁之前调用。实例仍然完全可用。
-
在这个钩子函数里面解除一些全局或者自定义事件。
-
-
destroyed
-
实例销毁后调用。
-
该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。
-
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>VUE@2生命周期</title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
</head>
<body>
<div id="app">
{{ message }}
</div>
<div class="test">
{{ msg }}
</div>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
});
</script>
<script type="text/javascript">
const myVue = new Vue({
el: ".test",
data: {
msg: "在控制台输入 myVue.msg=666666,可以改变值触发更新前,更新后"
},
beforeCreate: function () {
console.log("建立前 --- beforeCreate");
},
created: function () {
// 在实例创建之后同步调用。数据绑定,计算属性,方法,watcher/事件回调。
// 没有开始 DOM 编译,$el 还不存在,但是实例存在,即 this.a 存在,可打印出来 。
console.log("建立 --- created");
},
beforeMount: function () {
console.log("渲染前 --- beforeMount");
},
mounted: function () {
console.log("渲染后 --- mounted");
},
beforeUpdate: function () {
console.log("更新前 --- beforeUpdate");
},
updated: function () {
console.log("更新后 --- updated");
},
beforeDestroy: function () {
// 触发方式,在console里面打myVue.$destroy();
// 在开始销毁实例时调用。此时实例仍然有功能。
console.log("销毁前 --- beforeDestroy");
},
destroyed: function () {
// 触发方式,在console里面打myVue.$destroy(); 其中myVue.$destroy(true)是删除DOM节点,会触发detached函数,但是实例仍然存在
// 在实例被销毁之后调用。此时所有的绑定和实例的指令已经解绑,注意是解绑不是销毁,所有的子实例也已经被销毁。
console.log("已销毁 --- destroyed");
}
});
</script>
</body>
其他钩子函数
-
errorCaptured
-
在捕获一个来自后代组件的错误时被调用。
-
钩子函数的三个参数:错误对象、发生错误的组件实例、一个包含错误来源信息的字符串。
-
该钩子函数可以返回 false 以阻止该错误继续向上传播。
-
-
activated
- 被 keep-alive 缓存的组件激活时调用。
-
deactivated
- 被 keep-alive 缓存的组件失活时调用。
VUE@3组件的生命周期

-
setup() : 开始创建组件之前,在 beforeCreate 和 created 之前执行,创建的是 data 和 method
-
onBeforeMount() : 组件挂载到节点上之前执行的函数;
-
onMounted(): 组件挂载完成后执行的函数;
-
onBeforeUpdate(): 组件更新之前执行的函数;
-
onUpdated(): 组件更新完成之后执行的函数;
-
onBeforeUnmount(): 组件卸载之前执行的函数;
-
onUnmounted(): 组件卸载完成后执行的函数;
-
onActivated(): 被包含在
<keep-alive>中的组件,会多出两个生命周期钩子函数,被激活时执行; -
onDeactivated(): 比如从 A 组件,切换到 B 组件,A 组件消失时执行;
-
onErrorCaptured(): 当捕获一个来自子孙组件的异常时激活钩子函数。
生命周期执行顺序
生命周期函数的运行基本顺序是
setup->beforeCreate->created
单个组件
-
单组件初始化
setup->created->onBeforeMount->onRenderTracked->onMounted
-
单组件更新
onRenderTriggered->onBeforeUpdate->onUpdated
-
单组件卸载
onBeforeDestroy->onDestroyed
父子组件
-
父子组件初始化
- 父组件setup -> 父组件onBeforeMount -> 父组件onRenderTracked -> 子组件setup -> 子组件onBeforeMount -> 子组件onRenderTracked -> 子组件onMounted -> 父组件onMounted
-
父组件更新data,此data没传递给子组件
- 父组件onRenderTriggered-> 父组件onBeforeUpdate ->父组件 onUpdated
-
父组件更新data,此data传递给了子组件
- 父组件onRenderTriggered -> 父组件onBeforeUpdate -> 子组件onBeforeUpdate -> 子组件onUpdated -> 子组件onUpdated
-
子组件更新data
- 子组件onRenderTriggered -> 子组件onBeforeUpdate -> 子组件onUpdated
-
父子组件卸载
- 父组件onBeforeDestroy -> 子组件onBeforeDestroy -> 子组件onDestroyed -> 父组件onDestroyed
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生命周期函数。
本文详细介绍了React和Vue框架中组件的生命周期,包括挂载、更新和卸载阶段的关键钩子函数及其调用顺序。React的新版生命周期有所调整,移除了不安全的函数,并引入了新的生命周期方法。Vue2和Vue3的生命周期也进行了对比,强调了它们之间的相似性和差异性,如Vue3中新增的setup()函数。此外,文章还提到了错误处理和组件优化策略。
653

被折叠的 条评论
为什么被折叠?



