p>不少刚接触Vue的小伙伴,常会被生命周期绕晕—Vue2和Vue3的生命周期到底有啥区别?学的时候该抓哪些重点?今天咱们用大白话把这事儿掰碎了讲,从基础概念到实际场景,帮你彻底理清逻辑~
啥是Vue生命周期?
咱可以把Vue组件想象成一个“小机器人”,它从被创建出来,到把内容渲染到页面上,再到数据更新时跟着变,最后被销毁移除——这整个过程就是生命周期。
而每个关键节点(刚创建完”“DOM渲染好了”),Vue都会给咱留个“触发开关”,也就是生命周期钩子函数,咱写代码的时候,把逻辑塞到对应的钩子里,就能精准控制组件在哪个阶段干啥事儿~
举个简单例子:你想在页面刚加载完就请求后端数据,就得找到“组件DOM刚渲染完成”这个阶段的钩子,把请求代码放进去;要是想在组件销毁前清除定时器,就得找到“销毁前”的钩子做清理。
Vue2的生命周期“地图”:8个阶段全解析
Vue2里组件的一生被分成8个阶段,每个阶段对应一个钩子函数,咱逐个拆:
beforeCreate:组件刚“出生”,啥都没有
组件实例刚被创建,但data里的数据、methods里的方法还没被挂载到实例上,这时候你想打印this.data里的变量
,会得到undefined
——因为啥都没准备好,所以这个钩子用得少,基本没场景。
created:数据“到位”,请求常用这
组件实例初始化完成,data和methods已经能访问了!这时候最适合发Ajax请求(比如用axios拿列表数据),因为数据能存到data里,后续渲染也能用上。
举个🌰 做个博客列表:
export default { data() { return { list: [] } }, created() { axios.get('/api/blogs').then(res => { this.list = res.data; // 能直接给data赋值 }) } }
beforeMount:模板编译完,DOM还没挂
Vue已经把模板(比如<template>
)编译成虚拟DOM,但还没把虚拟DOM渲染成真实DOM挂载到页面上,这时候你打印this.$el
(组件对应的DOM元素),会发现是虚拟的,拿不到页面上真实的节点,这个阶段也少用,了解就行。
mounted:真实DOM就绪,操作DOM的黄金期
虚拟DOM变成真实DOM,并且挂载到页面上了!这时候能直接操作DOM,比如初始化第三方插件(轮播图、富文本编辑器)、给DOM元素绑定事件。
举个🌰 给轮播图插件初始化:
mounted() { new Swiper(this.$refs.swiper, { // this.$refs能拿到真实DOM loop: true }) }
beforeUpdate:数据变了,DOM还没跟
当组件里的data变化时,Vue会先触发这个钩子,这时候数据是新的,但页面上的DOM还是旧的,如果在这改数据,要小心触发无限更新循环(比如又改data,又触发beforeUpdate),所以尽量少用。
updated:DOM跟着数据变完了
数据更新导致的DOM重新渲染完成后,触发这个钩子,这时候能拿到最新的DOM状态,比如做一些DOM相关的后处理(但要注意:别在这又改data,否则又触发更新循环)。
beforeDestroy:组件要“死”,最后挣扎
组件销毁前触发,这时候组件实例还在,能访问data、methods,常用在这清除定时器、解绑自定义事件,避免内存泄漏。
举个🌰 清除定时器:
data() { return { timer: null } }, mounted() { this.timer = setInterval(() => { ... }, 1000) }, beforeDestroy() { clearInterval(this.timer); // 销毁前清掉定时器 }
destroyed:组件“入土”,彻底解绑
组件实例被销毁,所有事件监听器、子组件都被解绑/销毁,这时候再访问data、methods已经没意义了,这个钩子也少用,主要做最终的清理确认。
Vue3生命周期:组合式API带来的变化
Vue3推出了组合式API(Composition API),写法更灵活,生命周期也跟着变了样,核心逻辑集中在setup
函数里,钩子的命名和使用方式都有调整~
setup:替代beforeCreate和created
setup
是组合式API的入口函数,执行时机比beforeCreate还早!所以在setup
里,既能干beforeCreate的事儿(比如初始化响应式数据),也能做created的事儿(比如发请求),相当于把这两个钩子的逻辑都包进去了。
举个🌰 用setup发请求(结合onMounted,后面讲):
import { ref, onMounted } from 'vue' export default { setup() { const list = ref([]) // 注意:如果请求依赖DOM,最好放onMounted里;如果不依赖,setup里也能发 onMounted(() => { axios.get('/api/blogs').then(res => { list.value = res.data }) }) return { list } } }
新钩子:名字带on,功能对应Vue2
Vue3把Vue2的钩子改了名,还加了新钩子,咱对应着看:
Vue2钩子 | Vue3组合式钩子 | 作用 |
---|---|---|
beforeMount | onBeforeMount | 虚拟DOM创建完,真实DOM挂载前 |
mounted | onMounted | 真实DOM挂载完成,操作DOM |
beforeUpdate | onBeforeUpdate | 数据变了,DOM还没更新 |
updated | onUpdated | DOM跟着数据更新完成 |
beforeDestroy | onBeforeUnmount | 组件销毁前,清理资源 |
destroyed | onUnmounted | 组件销毁完成,解绑所有 |
另外Vue3还新增了两个调试用钩子:onRenderTracked
(追踪组件渲染时的依赖)和onRenderTriggered
(触发组件更新的原因),开发时用来排查性能问题很方便~
为啥要变?组合式API的优势
Vue2的选项式API(把data、methods、生命周期分开写),在处理复杂组件时,逻辑会被拆得很散(比如一个功能的代码分散在data、methods、mounted里),而组合式API通过setup
和钩子函数,能把同一功能的逻辑集中在一起,复用起来更方便。
比如做用户权限判断,Vue2得把权限逻辑拆到created(发请求)、mounted(DOM控制)、beforeDestroy(清除监听);Vue3可以把所有权限相关代码包在一个函数里,用onMounted
onBeforeUnmount
这些钩子,然后到处复用这个函数~
核心差异对比:从结构到时机,哪里变了?
光看单个钩子还不够,得从整体对比Vue2和Vue3生命周期的逻辑:
写法结构:选项式 vs 组合式
Vue2是选项式API,生命周期钩子作为单独的选项,和data、methods平级:
export default { data() { ... }, methods: { ... }, mounted() { ... } // 钩子是选项之一 }
Vue3组合式API中,生命周期钩子是导入后在setup里调用,逻辑更集中:
import { onMounted } from 'vue' export default { setup() { onMounted(() => { ... }) // 钩子是setup里的函数调用 } }
钩子命名:加on前缀,更统一
Vue3的生命周期钩子都加了on
前缀(比如onMounted
),和其他组合式API(如watch
computed
)的命名风格统一,一眼能看出是“钩子函数”。
覆盖的阶段:setup吃掉beforeCreate和created
Vue3里没有beforeCreate
和created
这两个钩子了!因为setup
的执行时机比它们还早,而且能完成数据初始化、发请求这些事儿,所以直接用setup
替代。
逻辑组织:分散 vs 集中
Vue2的选项式,一个功能的代码可能分散在多个钩子(比如发请求在created,DOM操作在mounted);Vue3组合式可以把同一功能的代码,用onMounted
onBeforeUnmount
等钩子包在一个函数里,维护起来更顺手。
实际开发咋选?新手学习避坑指南
搞清楚区别后,得落地到开发和学习里,这部分给你实用建议:
项目场景:Vue2和Vue3咋选钩子?
- 如果维护老项目(Vue2),就用选项式API,钩子写成
mounted() { ... }
这种形式; - 如果是Vue3新项目,优先用组合式API,在
setup
里导入onMounted
等钩子用; - Vue3也支持选项式API(兼容Vue2写法),但组合式是趋势,更适合复杂项目。
学习技巧:先懂阶段,再记API
别死记硬背钩子名字,先理解每个阶段的作用:
- 想操作DOM?等
mounted
/onMounted
(因为之前DOM没渲染); - 想发请求?Vue2用
created
,Vue3可以在setup
里用onMounted
(如果请求依赖DOM),或者直接在setup
里发(如果不依赖); - 想清理定时器、事件?Vue2用
beforeDestroy
,Vue3用onBeforeUnmount
。
然后多写小demo练手:比如做个带定时器的组件,用Vue2和Vue3分别实现,看钩子咋对应,清理逻辑咋写。
避坑指南:这些错误新手常犯
- ❌ 在
beforeMount
/onBeforeMount
里操作DOM:这时候真实DOM还没挂载,拿不到节点,白忙活; - ❌ 忘记清除定时器/事件监听:Vue2里不在
beforeDestroy
清,Vue3里不在onBeforeUnmount
清,都会导致内存泄漏(页面关了,定时器还在跑); - ❌ Vue3里还想写
created
:组合式API没有created
钩子,直接把逻辑放setup
或onMounted
里。
进阶思路:组合式API的逻辑复用
学懂生命周期后,试试用组合式API做逻辑复用,比如把“请求数据+加载状态+错误处理”封装成一个函数:
import { ref, onMounted } from 'vue' function useFetch(url) { const data = ref([]) const loading = ref(true) const error = ref(null) onMounted(async () => { loading.value = true try { const res = await axios.get(url) data.value = res.data } catch (e) { error.value = e } finally { loading.value = false } }) return { data, loading, error } } // 组件里直接用: setup() { const { data, loading, error } = useFetch('/api/blogs') return { data, loading, error } }
这样不管多少组件需要请求数据,都能复用useFetch
函数,生命周期钩子也被封装进去了,代码简洁又好维护~
Vue2和Vue3生命周期的核心区别,是写法和组织逻辑的变化——Vue2用选项式分散写,Vue3用组合式集中写,同时优化了钩子命名和执行时机,新手学习时,先抓“组件每个阶段该干啥”这个核心逻辑,再对应到具体API,多写多练自然就通了~要是你现在有个小项目,不妨用Vue2和Vue3分别实现同一个功能,对比着感受生命周期的差异,印象会更深~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。