介绍
vue的生命周期可以简单分为四个阶段:创建阶段,挂载阶段,运行阶段,销毁阶段。
Vue.js 的生命周期是指一个 Vue 实例从创建到销毁的各个阶段,每个阶段都有相应的生命周期钩子函数。这些钩子函数为开发者提供了在不同阶段介入组件逻辑的机会。
下面简单介绍下这几个钩子,以及每个阶段可以做什么、不可以做什么
一、创建阶段
beforeCreate
new Vue()之后触发的第一个钩子,此时数据观测 (data observer) 和 event/watcher 事件配置都还没有被执行
因此,在 beforeCreate
阶段,无法访问 data
、computed
、methods
、props
等实例的属性和方法,因为它们还没有被设置。
在 beforeCreate
阶段,可以做的事情比较有限,主要是用于以下场景:
- 插件的初始化:如果使用 Vue 插件,可以在这个钩子中进行插件的配置或初始化。
- 全局状态的注入:如果使用了全局状态管理(如 Vuex),可以在这个阶段注入全局状态。
created
实例创建完成后被立即调用。此时实例已完成数据观测 (data observer),属性和方法的运算,watch/event 事件回调。
挂载阶段还没开始,$el 属性目前尚不可用。
此时更改数据不会触发updated函数
在 created
阶段,可以做很多初始化的工作,例如:
- 访问和修改数据:在
created
钩子中,可以访问和修改data
中的数据,因为此时数据已经被响应式系统设置好了。 - 调用方法:可以调用
methods
中定义的方法来执行一些操作。 - 进行 API 调用:如果需要在组件创建时从服务器获取数据,可以在这个钩子中进行 API 调用,并将数据存储在组件的数据属性中。
- 设置定时器或订阅:可以在这个阶段设置定时器或者订阅外部事件源,但要记得在组件销毁时清理它们。
尽管 created
钩子允许访问数据和方法,但是此时组件的 DOM 还未渲染,因此不要试图在这个阶段进行任何 DOM 操作。如果需要操作 DOM,应该在 mounted
钩子中进行。
二、挂载阶段
beforeMount
这个生命周期钩子在实例被挂载之前调用,即在模板编译/渲染成真实 DOM 之前。此时,$el
属性还不可用,因为模板还没有渲染和挂载到 DOM 中。
在 beforeMount
阶段,可以做的事情比较有限,因为 DOM 还没有创建。但是,这个钩子在服务器端渲染(SSR)中很有用,因为它是在虚拟 DOM 渲染之前被调用的。在客户端渲染中,通常不需要使用 beforeMount
钩子。
mounted
mounted
钩子在实例被挂载后调用,此时组件的模板已经编译成了真实的 DOM 并挂载到了指定的元素上。现在可以访问到渲染好的 DOM 元素,$el
属性现在指向了组件的根 DOM 元素。
在 mounted
阶段,可以执行与 DOM 相关的操作,例如:
- 访问和操作 DOM:在
mounted
钩子中,可以执行任何涉及 DOM 的操作,比如使用this.$el
来获取组件的根元素,或者使用document.querySelector
来查询子元素。 - 与子组件交互:如果需要与子组件进行交互,并且这些交互依赖于子组件的挂载,那么可以在
mounted
钩子中进行。 - 第三方库的集成:如果需要集成非 Vue 的第三方库(比如 jQuery 插件),并且这些库需要操作 DOM,应该在
mounted
钩子中初始化它们。 - 开始动画:如果想在组件渲染后开始动画,可以在
mounted
钩子中设置动画的启动代码。
如果在 mounted
钩子中进行了数据修改,这可能会导致额外的渲染过程。因此尽量避免在 mounted
中修改数据,或者使用 created
钩子来进行数据初始化。
在服务端渲染 (SSR) 中,mounted
钩子只会在客户端执行。也就是说在服务器上生成的 HTML 不会执行 mounted
钩子中的代码,因为服务器上没有真实的 DOM 环境。
三、运行阶段
beforeUpdate
这个生命周期钩子在组件的数据发生变化,且DOM重新渲染之前被调用。此时,组件的虚拟DOM已经更新,但是这些改变还没有被应用到真实的DOM上。
在 beforeUpdate
阶段,可以执行的操作包括:
- 获取更新前的状态:可以访问现有的 DOM,比如检查某些元素的尺寸或位置,以便在更新后做一些对比或者过渡动画。
- 执行计算:如果有依赖于DOM状态的计算,这是一个进行计算的好时机,因为DOM还没有发生更新。
updated
updated
钩子在组件的数据变化导致的虚拟DOM重新渲染和打补丁之后被调用。在这个钩子被调用时,组件的DOM已经更新,所以可以执行依赖于DOM的操作。
在 updated
阶段,可以执行的操作包括:
- 操作更新后的DOM:这是进行DOM操作的正确时机,比如滚动到新元素的位置或者执行DOM相关的动画。
- 执行依赖于DOM的操作:如果组件需要根据最新的DOM状态执行操作(例如,获取新渲染的元素的尺寸或位置),这应该在
updated
钩子中完成。
注意,避免在 beforeUpdate
和 updated
钩子中修改状态,因为这可能会导致无限循环的更新。如果需要响应数据变化,请使用 computed 或 watchers 。
在使用这些钩子时,还要注意它们可能不止被调用一次。任何响应式数据的变化都可能触发这些钩子,所以应该避免产生副作用,或者确保副作用是可控的。
四、销毁阶段
beforeDestroy
beforeDestroy
钩子在Vue开始销毁组件实例之前被调用。在这个阶段,组件实例仍然是完全可用的,这意味着所有的数据绑定、子组件和观察者都是活跃的。
在 beforeDestroy
阶段,可以执行的操作包括:
- 清理定时器:如果在组件中设置了定时器(如
setTimeout
或setInterval
),这是清除它们的好时机,以避免它们在组件销毁后继续执行。 - 解绑自定义事件监听器:如果向DOM元素或组件实例添加了事件监听器,应该在这里移除它们,以防止内存泄漏。
- 取消外部订阅:如果组件订阅了外部服务或可观察对象(如RxJS Observables),现在是取消订阅的时候了。
- 停止正在进行的异步操作:如果有异步操作(如数据请求),并且你不希望它们在组件销毁后继续,应在此阶段中止这些操作。
destroyed
destroyed
钩子在Vue完成组件的销毁过程后被调用。此时,组件的指令已被解绑,事件监听器已被移除,子实例也被销毁。
在 destroyed
阶段,可以执行的操作包括:
- 执行清理任务:虽然Vue会自动清理其事件监听器和子组件,但如果存在非Vue管理的资源,如全局事件总线或插件,这是清除它们的一个好机会。
- 发送通知:如果有需要,可以在组件被销毁后发送通知或者调用回调函数,告知其他部分应用程序该组件已被销毁。
通常情况下,大多数清理和资源释放的工作应该在 beforeDestroy
钩子中完成,因为在 destroyed
钩子中,已经无法保证所有的子组件和依赖都是可用的。在 destroyed
钩子中执行的操作应该限制在那些不依赖于组件自身状态的行为。