1. app的mount
这是vue根节点挂载到指定DOM的阶段
单组件的生命周期阶段
其实vue单组件生命周期主要分为4个主要阶段的8个钩子函数:
- 组件的创建前后:
beforeCreate、created - 组件的挂载前后:
beforeMount、mounted - 组件数据更新前后:
beforeUpdate、updated - 组件的卸载前后:
beforeUnmount、unmounted
下面我们就针对这几个钩子具体来聊聊
2. beforeCreate
在实例初始化之后、进行数据侦听和事件/侦听器的配置之前同步调用。
在这个阶段,不能访问任何组件的响应式数据或事件(如: computed、watch、data等),也不要去操作响应式数据赋值之类的动作,操作了也会丢失。
3. created
在实例创建完成后被立即同步调用。这时候
数据侦听、计算属性、方法、事件、侦听器的回调函数都已配置完毕,但是还没挂载,且$elproperty 目前还不可用 在该阶段适合请求一些api初始化数据
在这个阶段,组件的一些响应式数据啊、事件啊之类的都处理好了,就可以去处理一些数据赋值了。
只是说这个时候还没开始挂载数据到模板或者render函数。
4. beforeMount
在挂载开始之前被调用:相关的
render函数首次被调用。
在这个阶段呢,就是按照我们写的模板或者render转变成虚拟DOM的结构树,,但是这个结构树还没挂载到真实的DOM上面去。这个时候不可以执行DOM操作,比如获取某个DOM节点之类的操作
5. mounted
在实例挂载完成后被调用,这时候
$el已经被挂载到文档内相应的位置了,但是mounted阶段不会保证所有的子组件也都被挂载完成,如果希望等整个视图都渲染完毕执行某些事情的话可以用nextTick,例:
import { nextTick, onMounted } from 'vue';
onMounted(() => {
nextTick(() => console.log('在这里可以干自己相干的事情'));
});
在这个阶段的话,其实可以理解为组件的渲染完成了,也已经挂载到对应的DOM节点上了,可以执行一些DOM相关的操作了,如果涉及到子组件的话,还是按照我们上面那样操作比较安全(nextTick)
6. beforeUpdate
在数据发生改变后,DOM 被更新之前被调用。这里适合在现有 DOM 将要被更新之前访问它,比如移除手动添加的事件监听器。
这个就好理解了,数据变更引发的准备开始视图变更。 但是我自己测试了一下,如果修改每个字段,但是该字段没在template使用,也就是说变更的字段不影响视图,是不会触发该钩子的(updated同理)
7. updated
在数据更改导致的虚拟DOM重新渲染和更新完毕之后被调用。但是同样的
updated阶段不会保证所有的子组件也都被挂载完成,如果希望等整个视图都渲染完毕执行某些事情的话可以用nextTick,例:
import { nextTick, onUpdated } from 'vue';
onUpdated(() => {
nextTick(() => console.log('在这里可以干自己相干的事情'));
});
这个阶段也好理解,就是数据更新引发的视图变更完成之后的回调。
但是我自己基本很少用beforeUpdate、updated这两个钩子,主要通过 watch、computed之后的操作吧。
如果涉及到DOM之类的操作的话,这两钩子就用的比较多吧。
8. beforeUnmount
在卸载组件实例之前调用。在这个阶段,实例仍然是完全正常的。
这是卸载前执行某些操作,比如说可以解绑一些事件啊,清除一些定时器啊,其他的垃圾回收操作之类的。
或者如果想记录一些数据,又没用keep-alive的话,比如记录搜索条件啥的也可以在这时候操作。
9. unmounted
卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。
10. activated
被 keep-alive 缓存的组件激活时调用。
activated、deactivated这两个的话主要场景:用户列表点击进入详情,然后详情返回到列表之类的。
大家如果用到keep-alive的话,还是要小心处理的。比如上面时候应该用缓存,什么时候不用缓存。
11. deactivated
被 keep-alive 缓存的组件失活时调用。
vue3的setup中调用生命周期钩子对应如下:
| 选项式 API | Hook inside setup |
|---|---|
beforeCreate | Not needed* |
created | Not needed* |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
errorCaptured | onErrorCaptured |
renderTracked | onRenderTracked |
renderTriggered | onRenderTriggered |
activated | onActivated |
deactivated | onDeactivated |
setup中没有beforeCreate和created,如果需要在这两个钩子中操作,直接在setup作用域内写你要操作即可。
这里附上官方给的生命周期图供大家参考:
父子组件的生命周期
刚才前面我们说的主要是单页面组件的生命周期,那如果是组件里面嵌套了子组件的时候,他的生命周期又该如何呢?
下面我做了一个测试,例:
1、当我们点击生命周期菜单进入的时候:
我们可以看到子组件的周期在父组件的mounted之前,子组件如果没用了keep-alive,忽略child activated即可。
2、当我们点击父组件的修改name按钮时:
我们可以看到子组件的生命周期都在父组件的updated之前
3、当我们点击其他菜单离开的时候:
我们可以看到子组件的周期也在父组件的unmounted之前都执行完毕了。
而且我们发现子组件的deactivated是在子组件的unmounted之前执行的
由上面两图我们得出结论:
- 挂载阶段为如下:
父beforeCreate > 父created > 父beforeMount > 子beforeCreate > 子created > 子beforeMount > 子mounted > 子activated > 父mounted
- 数据更新阶段为如下:
父beforeUpdate > 子beforeUpdate > 子updated > 父updated
- 卸载阶段为如下:
父beforeUnmount > 子beforeUnmount > 子deactivated > 子unmounted > 父unmounted
其他的一些钩子
12. errorCaptured
在捕获一个来自后代组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回
false以阻止该错误继续向上传播。
13. renderTracked
跟踪虚拟 DOM 重新渲染时调用。钩子接收
debugger event作为参数。此事件告诉你哪个操作跟踪了组件以及该操作的目标对象和键。
14. renderTriggered
当虚拟 DOM 重新渲染被触发时调用。和
renderTracked类似,接收debugger event作为参数。此事件告诉你是什么操作触发了重新渲染,以及该操作的目标对象和键。
errorCaptured、renderTracked、renderTriggered的详细说明可参考:传送门