在学习 Vue 的过程中,我逐渐意识到一个问题:**为什么同样是写数据、改数据,有些代码只能写在某些地方?为什么定时器、请求、事件绑定如果位置不对,就会出 bug?**答案几乎都指向同一个核心概念------Vue 生命周期。
Vue 生命周期并不是抽象的"理论名词",而是 Vue 在实例从创建到销毁的整个过程中,在关键时间点自动帮我们调用的一组函数。这些函数有固定的名字、固定的调用时机,而我们能做的,就是在合适的钩子中写合适的代码。
一、生命周期的本质:Vue 在"关键时刻"帮你调用函数
从第一个示例可以看到,生命周期也被称为生命周期回调函数、生命周期函数或生命周期钩子。它的本质并不复杂:
Vue 在内部流程的某些关键阶段,自动调用我们提前写好的函数1.引出生命周期
有几个非常重要的特性需要先明确:
- 生命周期函数的名字不能随便改
- 生命周期函数内部的代码由开发者决定
- 生命周期函数中的
this永远指向当前的 Vue 实例(vm)
也正因为 this 指向 vm,我们才能在生命周期中自由访问 data、methods、computed 等内容。
二、mounted:最常用、也最容易被误用的生命周期
在第一个示例中,页面上有一段非常直观的动画效果:文字透明度不断降低,又循环恢复。这个效果并不是通过操作 DOM 实现的,而是通过修改响应式数据 opacity 来完成的1.引出生命周期。
关键代码写在了 mounted() 中:
javascript
mounted() {
setInterval(() => {
this.opacity -= 0.01;
if (this.opacity <= 0) {
this.opacity = 1;
}
}, 16)
}
之所以把定时器写在 mounted,原因非常明确:
- 在
mounted之前,模板还没有真正渲染成 DOM - 只有在
mounted执行时,真实 DOM 已经挂载完成 - 所有依赖页面结构、DOM 或视图更新的逻辑,都应该放在这里
需要特别注意的是:
mounted 只会在"初次挂载"时调用一次,后续数据变化引起的重新渲染,并不会再次触发 mounted,而是走更新相关的生命周期。
三、为什么要学 beforeDestroy?------生命周期的"收尾阶段"
第二个示例在第一个基础上进一步完善了逻辑,引出了一个非常现实的问题:
**定时器什么时候清?Vue 实例销毁后会发生什么?**1.总结生命周期
在这个例子中,点击"点我停止"按钮,会调用:
kotlin
this.$destroy();
这行代码会手动销毁当前 Vue 实例,而在销毁之前,Vue 会调用 beforeDestroy()。
javascript
beforeDestroy() {
clearInterval(this.timer);
}
这正是生命周期的收尾价值所在。
在实际开发中:
mounted负责"初始化"beforeDestroy负责"清理善后"
例如:
- 清除定时器
- 解绑自定义事件
- 取消消息订阅
- 关闭 WebSocket 连接
如果不在销毁前清理这些内容,就会导致内存泄漏,甚至逻辑混乱。
另外,示例中还明确指出:
- Vue 实例销毁后,开发者工具中将不再显示该实例
- Vue 的自定义事件会失效
- 原生 DOM 事件依然存在
- 在
beforeDestroy中修改数据是没有意义的,因为更新流程已经不会再触发了1.总结生命周期
四、完整生命周期流程:从 beforeCreate 到 destroyed
第三个示例是对 Vue 生命周期最系统的一次演示,它几乎覆盖了所有常见的生命周期钩子,并通过 console.log 清晰地展示了调用顺序2.分析生命周期。
1️⃣ beforeCreate
这是 Vue 实例刚被创建时调用的钩子:
- data 尚未初始化
- methods 尚未初始化
- 访问
this.n得到的是undefined
这说明:
beforeCreate 几乎不适合写业务代码
2️⃣ created
在这个阶段:
- data 已经变成响应式数据
- methods 已经可以正常调用
- 但 DOM 还没有生成
如果你只关心数据、而不依赖页面结构,created 是一个可以使用的阶段。
3️⃣ beforeMount
此时:
- 模板已经编译完成
- 虚拟 DOM 已经生成
- 但还没有挂载到页面上
打印 this.$el 会发现,它还不是最终呈现在页面中的 DOM。
4️⃣ mounted(最重要)
这是生命周期中使用频率最高的一个钩子:
- 虚拟 DOM 已转为真实 DOM
- 页面已经完成首次渲染
$el就是页面中真实存在的 DOM
几乎所有涉及 DOM、视图、第三方库初始化的逻辑,都应该写在这里。
5️⃣ beforeUpdate / updated
当数据发生变化时:
beforeUpdate在视图更新之前触发updated在视图更新之后触发
它们常用于:
- 调试
- 对比更新前后的状态
- 少量特殊场景下的 DOM 同步操作
但在实际业务中,不建议滥用更新钩子。
6️⃣ beforeDestroy / destroyed
这是 Vue 实例生命周期的终点:
beforeDestroy:还能访问 data 和 methodsdestroyed:实例已经彻底不可用
一般来说,真正有价值的是 beforeDestroy,而 destroyed 很少使用。
五、从"记生命周期"到"会用生命周期"
通过这三段代码可以清楚地看到,生命周期并不是让人死记硬背的流程图,而是一套明确解决实际问题的时间节点机制:
- 初始化逻辑 →
mounted - 数据准备 →
created - DOM 操作 →
mounted - 更新监听 →
updated - 清理资源 →
beforeDestroy
当我真正理解这些钩子的调用时机和设计目的之后,很多之前"写着写着就出 bug"的问题,都会自然消失。
Vue 生命周期的学习重点,从来不是"有多少个钩子",而是------
在对的时间,做对的事。
六、总结
Vue生命周期钩子为开发者提供了在特定阶段介入实例生命周期的能力。通过合理使用这些钩子,我们可以:
- 在正确时机执行初始化操作
- 有效管理资源,防止内存泄漏
- 优化应用性能
- 更好地理解和控制应用状态
掌握生命周期不仅有助于编写更健壮的Vue应用,也是深入理解Vue响应式系统工作原理的关键。建议开发者在实际项目中多实践、多观察,逐步形成对生命周期各阶段的直观感受。