Vue3 生命周期钩子(超详细)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观
前言
在前端开发中,Vue3 的生命周期钩子是控制组件行为的核心工具。无论是数据初始化、DOM 操作,还是组件销毁时的资源清理,都离不开对生命周期的精准把握。对于编程初学者而言,理解这些钩子的触发顺序和使用场景,是掌握 Vue3 开发的关键一步。本文将通过 形象的比喻、代码示例和实战案例,帮助读者系统掌握 Vue3 生命周期钩子的原理与应用。
一、生命周期钩子的定义与作用
1. 什么是生命周期钩子?
生命周期钩子(Lifecycle Hooks)是 Vue3 在组件不同阶段自动触发的函数。它们如同组件的“成长轨迹”:从创建到销毁,每个阶段都有对应的钩子,开发者可以通过这些钩子在特定时刻执行自定义逻辑。
比喻:
想象一个新生儿的成长过程——出生、学习走路、上学、工作、退休。每个阶段都有标志性事件,而生命周期钩子就像这些阶段中的“里程碑”,开发者可以在此时插入自己的“庆祝活动”或“任务安排”。
2. 为什么需要生命周期钩子?
- 精准控制:在组件特定阶段执行代码(如挂载后操作 DOM)。
- 资源管理:避免内存泄漏(如销毁时移除定时器或监听器)。
- 状态初始化:在组件创建时加载数据或配置默认值。
二、Vue3 生命周期钩子的分类与触发顺序
Vue3 的生命周期钩子分为 选项式 API 和 组合式 API 两种写法。下表总结了关键钩子及其触发顺序:
钩子名称 | 阶段 | 作用与典型用例 |
---|---|---|
beforeCreate | 创建前 | 极少使用,通常用组合式 API 替代 |
created | 创建后 | 初始化数据或调用异步 API |
beforeMount | 挂载前 | 预处理数据(如计算属性) |
mounted | 挂载后 | 操作 DOM、绑定事件监听器 |
beforeUpdate | 更新前 | 保存 DOM 状态(如滚动位置) |
updated | 更新后 | 操作更新后的 DOM |
beforeUnmount | 销毁前 | 移除监听器、清理资源 |
unmounted | 销毁后 | 完成最后的清理工作 |
注意:在组合式 API 中,钩子通过
onXXX
形式调用(如onMounted
)。
三、关键钩子详解与实战案例
1. created
vs mounted
:数据初始化与 DOM 操作
created
在组件实例创建完成后调用,此时 模板编译未完成,无法操作 DOM。适合执行数据初始化或调用 API:
// 选项式 API
export default {
created() {
console.log("组件已创建,但 DOM 未挂载"); // 此时 document.querySelector("#myDiv") 会返回 null
this.fetchData(); // 启动数据请求
},
methods: {
async fetchData() {
const response = await fetch("https://api.example.com/data");
this.data = await response.json();
}
}
};
// 组合式 API
import { onMounted, onCreated } from 'vue';
export default {
setup() {
onCreated(() => {
console.log("组合式 API 的 created 钩子");
// 同步或异步操作
});
}
};
mounted
在组件首次渲染后调用,此时 DOM 已完全挂载,可安全操作 DOM:
// 选项式 API
mounted() {
console.log("DOM 已就绪,可以操作了");
this.$refs.myInput.focus(); // 通过 ref 聚焦输入框
}
// 组合式 API
onMounted(() => {
const inputElement = document.querySelector("#myInput");
inputElement?.focus();
});
比喻:
created
是“准备好材料”,mounted
是“组装完成”——只有后者才能对“成品”进行调整。
2. beforeUpdate
和 updated
:响应式更新的监控
这两个钩子在数据变化触发重新渲染时触发。例如,在列表更新时记录滚动位置:
// 选项式 API
export default {
data() {
return {
items: [],
scrollTop: 0
};
},
beforeUpdate() {
// 保存当前滚动位置
this.scrollTop = document.querySelector(".list-container").scrollTop;
},
updated() {
// 恢复滚动位置
document.querySelector(".list-container").scrollTop = this.scrollTop;
}
};
// 组合式 API
import { onBeforeUpdate, onUpdated } from 'vue';
export default {
setup() {
const scrollTop = ref(0);
const listContainer = ref(null);
onBeforeUpdate(() => {
scrollTop.value = listContainer.value.scrollTop;
});
onUpdated(() => {
listContainer.value.scrollTop = scrollTop.value;
});
return {
listContainer
};
}
};
3. beforeUnmount
和 unmounted
:资源清理
在组件销毁前(beforeUnmount
)和销毁后(unmounted
)执行清理操作。例如,清除定时器或事件监听器:
// 选项式 API
data() {
return {
timer: null
};
},
mounted() {
this.timer = setInterval(this.updateTime, 1000);
},
beforeUnmount() {
clearInterval(this.timer); // 避免内存泄漏
},
// 组合式 API
const timer = ref(null);
onMounted(() => {
timer.value = setInterval(() => {
// 更新时间逻辑
}, 1000);
});
onBeforeUnmount(() => {
clearInterval(timer.value);
});
四、常见误区与最佳实践
1. 避免在 created
中操作 DOM
由于 created
阶段 DOM 尚未生成,直接操作 DOM 会导致错误。例如:
// 错误示例:created 中操作 DOM
created() {
const element = document.getElementById("app"); // 可能为 null
element.style.color = "red"; // 可能引发错误
}
解决方案:将代码移至 mounted
钩子中。
2. 避免在 updated
中频繁触发副作用
updated
在每次数据变化时都会触发,若在此钩子中执行高耗计算(如遍历大数据集),可能导致性能问题。此时,优先使用 计算属性 或 watcher。
3. 组合式 API 的优先级
Vue3 推荐使用组合式 API(如 onMounted
),因其:
- 更灵活,支持解耦逻辑复用;
- 与 TypeScript 兼容性更好。
五、实战案例:计数器组件
通过一个计数器组件,演示多个钩子的协同工作:
<template>
<div>
<p>当前计数:{{ count }}</p>
<button @click="increment">+1</button>
<button @click="reset">重置</button>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from "vue";
const count = ref(0);
let timer = null;
// 组件挂载时启动计时器
onMounted(() => {
timer = setInterval(() => {
count.value++;
}, 1000);
});
// 组件销毁前清除计时器
onBeforeUnmount(() => {
clearInterval(timer);
});
const increment = () => {
count.value++;
};
const reset = () => {
count.value = 0;
};
</script>
功能说明:
onMounted
启动每秒自增计时器;onBeforeUnmount
清除计时器,防止内存泄漏;- 用户手动点击按钮时,
count
更新会触发视图响应式渲染。
六、总结与进阶方向
通过本文,读者应掌握 Vue3 生命周期钩子的核心概念、触发顺序及典型用例。关键要点总结如下:
- 钩子分类:创建、挂载、更新、销毁四大阶段;
- 核心钩子:
created
/mounted
处理数据与 DOM,beforeUnmount
清理资源; - 组合式 API 是未来开发趋势,需优先掌握。
进阶方向:
- 学习
watch
和watchEffect
实现动态响应; - 结合 Vue3 的
Suspense
组件处理异步加载; - 通过性能分析工具(如 Vue DevTools)观察生命周期触发细节。
掌握生命周期钩子,是 Vue3 开发者从“会用”到“精通”的必经之路。希望本文能帮助读者在实际项目中更高效、安全地控制组件行为!