Code前端首页关于Code前端联系我们

p>不少刚接触Vue的小伙伴,常会被生命周期绕晕—Vue2和Vue3的生命周期到底有啥区别?学的时候该抓哪些重点?今天咱们用大白话把这事儿掰碎了讲,从基础概念到实际场景,帮你彻底理清逻辑~

terry 5小时前 阅读数 10 #Vue

啥是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里没有beforeCreatecreated这两个钩子了!因为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钩子,直接把逻辑放setuponMounted里。

进阶思路:组合式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前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门