简言
每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤,比如设置好数据侦听,编译模板,挂载实例到 DOM,以及在数据改变时更新 DOM,在此总结下一个vue组件的生命周期描述。
vue3官网生命周期
生命周期
vue 组件实例的生命周期一般是从创建、挂载到卸载销毁;在此过程中,它也会运行被称为生命周期钩子的函数,让开发者有机会在特定阶段运行自己的代码。
图示:
图片来自于vue3官网。
流程
- Renderer — 渲染器开始渲染vue组件,开始创建vue组件实例。
- 合并组合式API(setup)的内容 。
- 触发 beforeCreate钩子函数。
- 初始化组件的配置(Options API)。
- 触发 created 钩子函数。
- 判断是否有预编译模板,没有的话实时编译模板。
- 触发 beforeMount 钩子函数,准备挂载vue组件实例。
- 进行挂载,将更新或优化处理好的内容进行渲染,添加或插入到dom节点中。
- 触发 mounted 钩子函数。
- 现在vue组件挂在好已经可以正常运行了,进入稳定实时运行阶段。
- 若组件中响应式数据发生改变,将触发 beforeUpdate函数,进入更新阶段。
- 重新渲染和更新vue组件。
- 触发 updated 钩子函数 。更新完毕,进入 稳定运行阶段。
- 当 vue组件不使用了,进入卸载销毁阶段,触发 beforeUnmount 钩子函数。
- 卸载销毁后,触发unmounted 钩子函数,生命周期完成。
从以上流程可以看出,一个普通的vue组件的生命周期至少要触发8个钩子函数。
钩子函数
了解钩子函数的用法和时机。
beforeCreate
在组件实例初始化完成之后立即调用。会在实例初始化完成、props 解析之后、data() 和 computed 等选项处理之前立即调用。
一般情况下,在beforeCreate中可以进行一些组件的初始化设置,例如全局变量、事件监听器等。
注意,组合式 API 中的 setup() 钩子会在所有选项式 API 钩子之前调用,beforeCreate() 也不例外。
interface ComponentOptions {
beforeCreate?(this: ComponentPublicInstance): void
}
created
在组件实例处理完所有与状态相关的选项后调用。
当这个钩子被调用时,以下内容已经设置完成:响应式数据、计算属性、方法和侦听器。然而,此时挂载阶段还未开始,因此 $el 属性仍不可用。
此时组件可以访问到props和data属性。在created中可以进行一些异步请求、事件监听器的注册等操作。
interface ComponentOptions {
created?(this: ComponentPublicInstance): void
}
created() {
console.log(' created 钩子函数')
}
beforeMount
在组件被挂载之前调用。当这个钩子被调用时,组件已经完成了其响应式状态的设置,但还没有创建 DOM 节点。它即将首次执行 DOM 渲染过程。
在此阶段,Vue实例已经生成了一个虚拟DOM,并且将要被渲染到实际的DOM元素上。在beforeMount中可以进行一些DOM相关的操作,例如获取DOM节点、样式等。
interface ComponentOptions {
beforeMount?(this: ComponentPublicInstance): void
}
beforeMount() {
console.log(' beforeMount 钩子函数')
},
mounted
在组件被挂载之后调用。
组件在以下情况下被视为已挂载:
-
所有同步子组件都已经被挂载。(不包含异步组件或<Suspense> 树内的组件)
-
其自身的 DOM 树已经创建完成并插入了父容器中。注意仅当根容器在文档中时,才可以保证组件 DOM 树也在文档中。
这个钩子通常用于执行需要访问组件所渲染的 DOM 树相关的副作用,意思是已经渲染好了,你可以在这做些渲染后的操作(不触发更新),此时,Vue实例已经被渲染到了实际的DOM元素上,可以访问到DOM节点和计算后的样式。
interface ComponentOptions {
mounted?(this: ComponentPublicInstance): void
}
mounted() {
console.log(' mounted 钩子函数')
},
beforeUpdate
在组件即将因为一个响应式状态变更而更新其 DOM 树之前调用。
这个钩子可以用来在 Vue 更新 DOM 之前访问 DOM 状态。在这个钩子中更改状态也是安全的。
interface ComponentOptions {
beforeUpdate?(this: ComponentPublicInstance): void
}
beforeUpdate() {
console.log(' beforeUpdate 钩子函数')
}
updated
在组件因为一个响应式状态变更而更新其 DOM 树之后调用。
父组件的更新钩子将在其子组件的更新钩子之后调用。
这个钩子会在组件的任意 DOM 更新后被调用,这些更新可能是由不同的状态变更导致的。
不要在 updated 钩子中更改组件的状态,这可能会导致无限的更新循环!
interface ComponentOptions {
updated?(this: ComponentPublicInstance): void
}
updated() {
console.log(' updated 钩子函数')
},
beforeUnmount
在一个组件实例被卸载之前调用。
当这个钩子被调用时,组件实例依然还保有全部的功能。在此阶段,组件即将被销毁,可以进行一些清理操作,例如取消事件监听器和定时器等等。
interface ComponentOptions {
beforeUnmount?(this: ComponentPublicInstance): void
}
beforeUnmount() {
console.log(' beforeUnmount 钩子函数')
},
unmounted
在一个组件实例被卸载之后调用。
一个组件在以下情况下被视为已卸载:
-
其所有子组件都已经被卸载。
-
所有相关的响应式作用 (渲染作用以及 setup() 时创建的计算属性和侦听器) 都已经停止。
可以在这个钩子中手动清理一些副作用,例如计时器、DOM 事件监听器或者与服务器的连接。
interface ComponentOptions {
unmounted?(this: ComponentPublicInstance): void
}
unmounted() {
console.log(' unmounted 钩子函数')
}
示例
<template>
<div>选项式组件</div>
</template>
<script lang="ts">
export default {
setup() {
return {}
},
data() {
return {}
},
beforeCreate() {
console.log('beforeCreeate 钩子函数')
},
created() {
console.log(' created 钩子函数')
},
beforeMount() {
console.log(' beforeMount 钩子函数')
},
mounted() {
console.log(' mounted 钩子函数')
},
beforeUpdate() {
console.log(' beforeUpdate 钩子函数')
},
updated() {
console.log(' updated 钩子函数')
},
beforeUnmount() {
console.log(' beforeUnmount 钩子函数')
},
unmounted() {
console.log(' unmounted 钩子函数')
}
}
</script>
结语
vue内置了一些具有特定功能的vue组件,这些组件除了会触发这些钩子函数外,还会触发对应的组件钩子函数。