目录
[vue 2生命周期](#vue 2生命周期)
[vue 3生命周期](#vue 3生命周期)
[1 .onErrorCaptured](#1 .onErrorCaptured)
[2. activated /onActivated](#2. activated /onActivated)
基本概念
vue实例从创建到销毁的过程就是生命周期。也就是,创建,初始化数据,编译模版,挂载DOM到渲染,更新到渲染,销毁等一系列过程,在这些过程中,它也会运行被称为生命周期钩子的函数,让开发者有机会在特定阶段运行自己的代码。
主要分为四个阶段:创建前后,挂载前后,更新前后,销毁前后,以及一些特殊场景生命周期
vue 2生命周期
创建前后
1. beforeCreate
在实例初始化(new Vue())之后,进行数据侦听和事件/侦听器的配置之前同步调用。
1.这个阶段,数据是获取不到的,并且真实dom元素也是没有渲染出来的
2.可以在此阶段添加加loading事件,在加载实例时触发
2. created
在实例创建完成后被立即调用。在这一步,实例已完成数据侦听、计算属性和方法的运算、watch/event 事件回调。
1.这个阶段,数据可以访问到了 ,但是**$el(element节点)不可见**,或者说页面当中真实DOM还是没有渲染出来
2.可以在此阶段进行相关初始化事件的绑定、如在这里结束loading事件,也可以进行异步请求操作
挂载前后
3. beforeMount
在挂载开始之前被调用。相关的 render 函数首次被调用。该钩子在服务器端渲染期间不被调用。
1.在这个阶段,完成了DOM的初始化,但仍然无法获取到具体的DOM元素,因为vue还没有进行根节点挂载,但是根节点已经创建完成,下面Vue对DOM的操作将围绕这个根节点进行。
2.beforeMount这个阶段是过渡性的,在项目中使用得比较少
4. mounted
实例被挂载后被调用。此时数据挂载完毕,真实dom元素也已经渲染完成了,也就是能获取到数据和DOM元素了
1.可以在此阶段进行一些实例化相关的操作
2.注意: mounted 不会保证所有的子组件也都被挂载完成。如果你希望等到整个视图都渲染完毕再执行某些操作,可以在 mounted 内部使用 vm.$nextTick
javascriptmounted: function () { this.$nextTick(function () { // 仅在整个视图都被渲染之后才会运行的代码 }) }
更新前后
5. beforeUpdate
在数据发生改变后,DOM 被更新之前被调用。此阶段的视图数据和DOM元素数据并不同步
1.这里适合在现有 DOM 将要被更新之前访问它,比如移除手动添加的事件监听器。
2.注意:这个钩子函数在挂在完成且数据发生改变后才会被调用,它获取到的是更新前的DOM
6. updated
在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用。这个时候数据发生了改变,并且视图页面也已经完成了更新,因此,该阶段看到的DOM元素的内容是最新内容。
1.当这个钩子被调用时,组件 DOM 已经更新,所以现在可以执行依赖于 DOM 的操作。
2.注意:要避免更改状态,因为这可能会导致无限更新循环。如果要响应状态改变,通常最好使用计算属性或 watcher 。
3.注意 :
updated
会在组件的任意 DOM 更新后被调用,这些更新可能是由不同的状态变更导致的,因为多个状态变更可以在同一个渲染周期中批量执行 (考虑到性能因素)。如果你希望等到整个视图都渲染完毕,可以在updated
里使用 [vm.nextTick](https://v2.cn.vuejs.org/v2/api/#vm-nextTick "vm.nextTick"):
javascriptupdated: function () { this.$nextTick(function () { // 仅在整个视图都被重新渲染之后才会运行的代码 }) }
更新过程:
1)数据变化:当Vue组件的数据发生变化时,Vue会开始一个更新过程。
2)虚拟DOM比对 :Vue会基于新的数据生成一个新的虚拟DOM树,并与旧的虚拟DOM树进行比对(这个过程通常称为"diff")。这个比对过程是为了找出需要被更新的真实DOM的最小部分。
3)DOM更新:一旦确定了需要更新的部分,Vue会将这些变化应用到真实的DOM上。
4)生命周期钩子 :在DOM更新之后,Vue会调用updated
生命周期钩子 。这意味着,在updated
钩子被调用时,组件的DOM已经是最新的状态,反映了最新的数据。
销毁前后
7. beforeDestroy
实例销毁之前调用。在此阶段Vue实例仍然完全可用,包括它的数据(data)、计算属性(computed)、方法(methods)以及 DOM 元素(通过 this.$el 访问)。
此阶段可以手动清理一些副作用,例如计时器、DOM 事件监听器或者与服务器的连接。
8. destroyed
实例销毁后调用。DOM元素被销毁,此时对应 的Vue 实例所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。
Vue实例失去活性,完全丧失功能
上图来自vue2官方文档生命周期图示
代码示例
html
<template>
<div id="app">
<p id="text">{{msg}}</p>
<button @click="msgChange()">更新data</button>
</div>
</template>
<script>
export default {
data () {
return {
msg: 'hello'
}
},
methods: {
msgChange(){
this.msg ='我更新了'
}
},
beforeCreate(){
console.log('beforeCreate阶段:');
console.log(this.msg,this.$el)
},
created () {
console.log('createde阶段:');
console.log(this.msg, this.$el)
},
beforeMount () {
console.log('beforeMounte阶段:')
console.log(this.msg,this.$el)
},
mounted () {
console.log('mountede阶段:')
console.log(this.msg, this.$el)
},
beforeUpdate(){
console.log('beforeUpdate阶段:');
console.log(this.msg,this.$el.innerHTML)
},
updated () {
console.log('updated阶段:');
console.log(this.msg, this.$el.innerHTML)
},
beforeDestroy(){
console.log('beforeDestroy阶段:');
console.log(this.msg, this.$el.innerHTML)
},
destroyed(){
console.log('已销毁');
}
}
</script>
页面初始化挂载完成后(会触发创建前后,挂在前后4个钩子函数):
页面初始化挂载完成并更新后(会触发更新前后2个钩子函数):
vue 3生命周期
选项式
Vue 3
中的选项式生命周期钩子基本上与Vue 2
保持一致,它们都是定义在Vue
实例的对象参数中的函数,在Vue
实例的生命周期的不同阶段被调用。
主要区别如下(其余基本一致):
|--------|-------------------|-------------------|
| 区别 | vue 3选项式 | vue 2 |
| 销毁前 | beforeUnmount | beforeDestroy |
| 销毁后 | unmounted | destroyed |
vue 3选项式中将销毁前后(或者说卸载前后)的周期函数由 "beforeDestroy 和destroyed "变成了 "beforeUnmount 和unmounted "。与挂载前后的 "beforeMount 和mounted" 相互对应。
javascript
export default {
beforeUnmount() {
console.log('beforeUnmount')
},
unmounted() {
console.log('unmounted')
}
}
组合式
Vue3的组合式API提供了一套新的生命周期钩子,与Vue2中的选项式生命周期钩子有着对应关系:
|-------|---------------------|-------------------|
| / | vue 3组合式 | vue 2 |
| 创建前后 | setup | beforeCreate |
| 创建前后 | setup | created |
| 挂载前 | onBeforeMount | beforeMounte |
| 挂载后 | onMounted | mounted |
| 更新前 | onBeforeUpdate | beforeUpdate |
| 更新后 | onUpdated | updated |
| 销毁前 | onBeforeUnmount | beforeDestroy |
| 销毁后 | onUnmounted | destroyed |
总的来说:
Vue3 使用 Composition API 引入了新的生命周期钩子,但是它们和 Vue2 中的生命周期钩子有直接的对应关系。vue 3使用setup()来代替 beforeCreate 和 created,并提供了一系列"on"钩子函数。
上图来自vue 3官方文档生命周期图示
代码示例
javascript
import { onBeforeMount, onMounted } from 'vue'
export default {
setup() {
onBeforeMount(() => {
console.log('onBeforeMount')
})
onMounted(() => {
console.log('onMounted')
})
return {}
}
}
注意:选项式中周期函数需要引入才能使用
特殊场景生命周期
|-------------------|---------------------|-------------------------|
| Vue 2 | vue 3 | 功能 |
| errorCaptured | onErrorCaptured | 捕获一个来自后代组件的异常时调用 |
| activated | onActivated | 被 keep-alive 缓存的组件激活时调用 |
| deactivated | onDeactivated | 被 keep-alive 缓存的组件停用时调用 |
以vue 3举例:
1 .onErrorCaptured
javascript
function onErrorCaptured(callback: ErrorCapturedHook): void
type ErrorCapturedHook = (
err: unknown,
instance: ComponentPublicInstance | null,
info: string
) => boolean | void
在捕获一个来自后代组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false
以阻止该错误继续向上传播。
错误可以从以下几个来源中捕获:
- 组件渲染
- 事件处理器
- 生命周期钩子
setup()
函数- 侦听器
- 自定义指令钩子
- 过渡钩子
你可以在 errorCaptured()
中更改组件状态来为用户显示一个错误状态。注意不要让错误状态再次渲染导致本次错误的内容,否则组件会陷入无限循环。
2. activated /onActivated
1.<KeepAlive> 包裹动态组件时,会缓存不活跃的组件实例,而不是销毁它们(提升性能)。同时这些组件将拥有onActivated和onDeactivate两个生命周期。
切换组件时一般情况下会自动销毁组件,对于可能会频繁切换的组件,消耗的性能可能会较大,组件的某些需要缓存的数据也会被初始化。而<KeepAlive>很好的解决了这个问题。
-
任何时候都只能有一个活跃组件实例作为 <KeepAlive> 的直接子节点。
-
当一个组件在 <KeepAlive> 中被切换时,它的 activated 和 deactivated 生命周期钩子将被调用,用来替代 mounted 和 unmounted。这适用于 <KeepAlive> 的直接子节点及其所有子孙节点。
activated:若组件实例是 <KeepAlive>缓存树的一部分,当组件从 DOM 中被移除时调用。
**onActivated:**若组件实例是 <KeepAlive>缓存树的一部分,当组件被插入到 DOM 中时调用。
javascript
<template>
<KeepAlive>
<component :is="activeComponent" />
</KeepAlive>
</template>
<script setup>
import { onActivated, onDeactivated } from 'vue'
let activeComponent = true//控制component是在缓存树还是DOM树
onActivated(() => {
// 调用时机为首次挂载
// 以及每次从缓存中被重新插入时
})
onDeactivated(() => {
// 在从 DOM 上移除、进入缓存
// 以及组件卸载时调用
})
</script>
更多vue生命周期详细内容: vue 3 组合式 API:生命周期钩子 vue 2 API:生命周期钩子
若有错误或描述不当的地方,烦请评论或私信指正,万分感谢 😃