Vue2至Vue3生命周期详解

本文详细解释Vue2及Vue3的生命周期,并在最后列出了关于Vue生命周期常见的面试题,便于各位小伙伴快速学习相关内容!

一、vue2的生命周期

  1. beforeCreate

在实例初始化之后,进行数据侦听和事件/侦听器的配置之前同步调用

详解:

  • 获取不到数据属性(此时 data、props、computed、methods 等都还未初始化),尝试访问 this.xxx 会返回 undefined
  • 模板尚未编译,真实DOM不存在,访问this.$el为undefined
  • 事件系统尚未初始化,无法使用this.$on、emit等方法
  1. created

在实例创建完成之后被立即同步调用。在这一步中,实例已完成对选项的处理,意味着以下内容已被配置完毕:数据侦听、计算属性、方法、事件/侦听器的回调函数。然而,挂载阶段还没开始,且$el.property目前暂不可用

详解:

  • 可访问和修改数据,data、props、computed、methods 等都已配置完成
  • DOM还未挂载,this.$el 仍为 undefined
  • 事件系统初始化完毕,可使用this.$on、emit等方法
  • 可用于调用接口初始化数据

$el.property 中的 el指的是Vue实例的根DOM元素(即挂载的DOM节点,一般为id为app的那个

元素),而.proterty是一个泛指的占位符,表示访问的任意DOM属性和方法( mounted 生命周期之后可用)

  1. beforeMount

在实例挂载到 DOM 之前触发,此时 Vue 已经完成了模板(template)的编译(将模板转换为渲染函数render),但尚未将生成的虚拟 DOM 替换到页面上变成真实DOM

render函数的作用是生成虚拟DOM,无论是通过模板(template)还是直接手写的 render 函数,最终都会被 Vue 转换为一个 render 函数

详解:

  • 与created的区别就是到达beforeMount钩子时模板已经编译完成,存在虚拟DOM
  • 此时this.$el访问的是原始元素(区分于实例的元素),不是真实DOM
  1. mounted

实例被挂载之后调用,标志着组件已经完成了初始渲染,真实 DOM 已经创建并插入到文档中。但是 mounted 不会保证所有的子组件也都被挂载完成,可以使用nextTick邓达斯渲染完毕再执行相关操作

详解:

  • DOM 完全可用,使用this.$el可以得到实例上真实的dom
  • 计算属性已经完成首次计算,所有初始数据都已经反映在视图上了
  • 但子组件的mounted可能尚未执行,可以使用nextTick等待整个视图渲染完毕
  1. beforeUpdate(防抖节流)

在数据变化后、DOM 更新前被调用,为开发者提供了一个干预更新过程的机会

详解:

  • 不会在初始化时执行,仅在数据变化导致重新渲染时触发
  • 数据已经是新值,计算属性已经重新计算、但是DOM为旧的
  • 适合临时添加事件监听器、保存当前的DOM状态(如滚动位置)
  • 不应该执行耗时操作,容易阻塞渲染
  • 多DOM更新操作考虑使用requestAnimationFrame进行视觉更新
  1. updated(防抖节流)

在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用。

详解:

  • 在此钩子中修改数据可能导致无限更新循环,应该避免状态修改
  • 如需要响应数据变化,应使用计算属性或watcher
  • 常用于清除定时器、取消事件监听、清理第三方库实例
  1. beforeDestroy

组件即将被销毁,但所有功能仍完整可用

详解:

  • 用于清理组件专用资源、取消副作用操作、执行销毁前的状态保存
  • vue不会自动清理监听器和第三方库实例,未清理的资源可能导致内存泄漏
  1. destroyed

实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁

详解:

  • 日志记录
  • 通知外部系统组件以及销毁
  • 清理不依赖实例的状态

二、vue3的生命周期

1、写法

  • beforeMount —> onBeforeMount
  • mounted —> onMounted
  • beforeUpdate —> onBeforeUpdate
  • updated —> onUpadate
  • beforeDetory —> onBeforeUnmount
  • detory —> onUnmounted

2、setup替代 —> beforeCreate和created

  • setup函数会在beforeCreate之前执行,此时组件尚未初始化(数据/方法未生成)
  • 但是原来写在beforeCreate和created的逻辑可以写在setup中
  • 用于定义响应式数据、声明方法、组合逻辑

组件生命周期图示

三、vue初始化过程

  1. 初始化阶段

    初始化生命周期相关属性、事件系统、渲染函数相关属性

    • 对应beforeCreate:实例刚初始化,无法访问到data、computed、methods
  2. 数据观测阶段

    初始化data、props、methods、computed、watch等属性

    • vue会遍历data对象上的属性,使用Object.defineProperty(vue2)或Proxy(vue3)将它们转换为getter/setter
      • 当组件渲染时,访问数据属性触发getter,将当前Watcher(依赖)收集到熟悉的依赖列表中
      • 当数据变化时,setter会通知所以依赖进行更新
    • 对应created钩子:已完成数据观测、可访问data、computed、methods,但尚未挂载DOM,$el不可用
  3. 模板编译阶段

    vue将模板(template)编译为渲染函数(render),编译过程会将v-if\v-for等语法转换为JS代码

    • 检查是否有template选项,有则编译为render函数,无则将el的outerHTML作为模板编译
    • 将template编译为抽象语法树(AST)
    • 优化AST(标记出静态节点:静态节点再后续变更会被跳过)
    • 生成render
  4. 挂载阶段

    • 创建组件实例的渲染Watcher
    • 执行beforeMount:模板编译完成,即将首次渲染
    • 执行render,生成虚拟DOM,与旧DOM进行比较,计算出最小变更,应用变更到真实DOM上
    • 创建真实DOM并替换el(或插入el内部)
    • 执行mounted:实例已经挂载到DOM,可访问$el,但不保证所有组件都已经渲染
  5. 更新阶段

    当响应式数据变化时,触发渲染Watcher更新

    • 数据变化,DOM更新之前执行beforeUpdate
    • DOM更新完成之后执行updated:在这个钩子不要修改状态,否则会无限循环
  6. 卸载阶段

    • 在实例销毁之前会执行beforeUnmount(vue2是beforedestory),此时实例完全可用
    • 实例销毁之后,所有绑定移除,执行unmounted/destoryed

四、生命周期面试题

1、生命周期钩子在什么时候调用?

答:

  • beforeCreate在实例初始化之后,数据观测之前调用
  • created在实例创建完成,即数据观测也已经完成,属性、事件和方法可以访问,但无dom
  • beforeMounted在实例挂载之前调用,render函数首次调用完成,存在虚拟DOM
  • mounted在实例挂载完毕后调用,可访问属性方法,虚拟DOM已经转换为真实DOM
  • beforeUpdate在数据更新、但DOM还未更新时调用
  • updated在数据更新导致的DOM重新渲染之后调用
  • beforeDestory在实例销毁之前调用,此时实例还存在
  • Destory在实例销毁之后调用

2、生命周期钩子内部可以做什么事情?

  • created 实例已经创建完成,数据完成观测,可以进行数据、资源的请求。
  • mounted 实例已经挂载完成,拿到了vue实例的DOM,可以进行一些DOM操作。
  • beforeUpdate 可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
  • updated 可执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态, 因为这可能会导致更新无限循环。 该钩子在服务器端渲染期间不被调用。
  • beforeDestroy 可以在组件销毁之前进行一些优化操作,比如关闭定时器,关闭监听,用来销毁一些离开这个页面不愿理还进行的操作。

3、created和mounted的区别?

答:

  • created:实例已经创建完成,数据完成观测、但是DOM还未挂载
  • mounted:DOM已经挂载,可以操作真实的DOM

4、在哪个请求发起AJAX请求最合适?

答:在created钩子发起请求最合适,因为

  • 此时数据已经完成观测,可以设置响应式数据
  • 比mounted更早执行,能更早获取数据
  • 但是需要DOM信息的请求应该放在mounted+$nextTick中
  • nextTick将回调延迟到下次DOM更新循环之后执行

5、第一次加载页面会触发那些钩子

答:前面四个钩子

6、简述父子组件的生命周期

总结起来就是三个大阶段都是子组件的最后一步由父组件完成

  • 渲染阶段:

    父组件 beforeCreate

    父组件 created

    父组件 beforeMount

    开始编译父组件模板

    子组件 beforeCreate

    子组件 created

    子组件 beforeMount

    子组件 mounted (此时子组件DOM已挂载)

    父组件 mounted (父组件DOM最终挂载完成)

  • 更新阶段

    父组件 beforeUpdate

    子组件 beforeUpdate

    子组件 updated

    父组件 updated

  • 销毁阶段

    父组件 beforeDestroy/beforeUnmount

    子组件 beforeDestroy/beforeUnmount

    子组件 destroyed/unmounted

    父组件 destroyed/unmounted

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值