当前位置: 首页 > news >正文

Vue 3 生命周期钩子详解

一、Vue 生命周期概述

Vue 组件的生命周期指的是一个 Vue 实例从创建到销毁的整个过程。在这个过程中,Vue 提供了一系列的"钩子"(hooks),允许开发者在特定阶段插入自己的代码,实现特定的功能。

Vue 3 虽然引入了 Composition API,但依然保留了选项式 API 中的生命周期概念,只是部分钩子名称有所变化。

二、Vue 3 生命周期图示

初始化
│
├─ beforeCreate
│     ↓
├─ created
│     ↓
├─ beforeMount
│     ↓
├─ mounted
│     ↓
├─ beforeUpdate
│     ↓
├─ updated
│     ↓
├─ beforeUnmount (Vue 2中的beforeDestroy)
│     ↓
├─ unmounted (Vue 2中的destroyed)
│
└─ 其他特殊钩子
   ├─ activated
   ├─ deactivated
   └─ errorCaptured

三、主要生命周期钩子详解

1. beforeCreate

调用时机:在实例初始化之后,数据观测(data observer)和事件/侦听器配置之前被调用。

特点

  • 此时组件实例刚被创建
  • data、methods、computed等选项还未初始化
  • 无法访问组件的数据和方法

使用场景

  • 极少使用
  • 可以在插件中使用来注入一些全局属性

2. created

调用时机:在实例创建完成后被立即调用。

特点

  • 已完成数据观测(data observer)
  • 属性和方法的运算,watch/event事件回调已设置
  • 但尚未挂载DOM,$el属性尚不可用

使用场景

  • 适合执行需要访问数据的初始化操作
  • 可以在此处发起异步请求获取数据
  • 可以访问响应式数据,但无法操作DOM
export default {
  data() {
    return {
      message: 'Hello Vue!'
    }
  },
  created() {
    console.log(this.message) // 'Hello Vue!'
    console.log(this.$el) // undefined
  }
}

3. beforeMount

调用时机:在挂载开始之前被调用,相关的render函数首次被调用。

特点

  • 编译模板已完成,但尚未将模板渲染到页面中
  • 这是能在挂载前修改数据的最后机会

使用场景

  • 很少使用
  • 可以在服务端渲染时使用

4. mounted

调用时机:实例被挂载后调用,这时el被新创建的vm.$el替换。

特点

  • 组件已挂载到DOM上
  • 可以访问DOM元素
  • 所有同步子组件也已被挂载(但不保证所有异步子组件都已挂载)

使用场景

  • 需要操作DOM的初始化
  • 可以在此处使用第三方库初始化
  • 可以获取元素尺寸或位置
export default {
  mounted() {
    console.log(this.$el) // 可以访问DOM元素
    this.$nextTick(() => {
      // 确保整个视图都已渲染
    })
  }
}

5. beforeUpdate

调用时机:数据更新时调用,发生在虚拟DOM打补丁之前。

特点

  • 可以在更新前访问现有的DOM
  • 适合在更新之前访问现有的DOM,比如手动移除已添加的事件监听器

使用场景

  • 极少使用
  • 可以在更新前获取DOM状态

6. updated

调用时机:由于数据更改导致的虚拟DOM重新渲染和打补丁后调用。

特点

  • 组件DOM已经更新
  • 可以执行依赖于DOM的操作
  • 避免在此钩子中更改状态,可能会导致无限更新循环

使用场景

  • 当需要根据DOM变化执行操作时
  • 使用$nextTick确保所有子组件都已重新渲染
export default {
  updated() {
    this.$nextTick(() => {
      // 所有视图已更新后执行的代码
    })
  }
}

7. beforeUnmount (Vue 2中的beforeDestroy)

调用时机:在卸载组件实例之前调用。

特点

  • 实例仍然完全可用
  • 这是销毁前的最后机会

使用场景

  • 清理定时器
  • 取消事件监听
  • 取消未完成的网络请求
export default {
  beforeUnmount() {
    clearInterval(this.timer)
    window.removeEventListener('resize', this.handleResize)
  }
}

8. unmounted (Vue 2中的destroyed)

调用时机:卸载组件实例后调用。

特点

  • 所有指令都已解绑
  • 所有事件监听器都已移除
  • 所有子实例也都被卸载

使用场景

  • 执行最后的清理工作
  • 报告组件销毁

四、特殊生命周期钩子

1. activated

调用时机:被keep-alive缓存的组件激活时调用。

2. deactivated

调用时机:被keep-alive缓存的组件失活时调用。

使用场景

  • 保存/恢复组件状态
  • 暂停/恢复动画
export default {
  activated() {
    // 恢复组件状态
    this.startAnimation()
  },
  deactivated() {
    // 保存组件状态
    this.pauseAnimation()
  }
}

3. errorCaptured

调用时机:捕获来自后代组件的错误时调用。

参数

  • err: 错误对象
  • vm: 发生错误的组件实例
  • info: 包含错误来源信息的字符串

特点

  • 可以返回false阻止错误继续向上传播
  • 可以在此钩子中执行错误处理逻辑
export default {
  errorCaptured(err, vm, info) {
    console.error(`Error: ${err}\nInfo: ${info}`)
    // 发送错误报告
    sendErrorToServer(err)
    // 阻止错误继续向上传播
    return false
  }
}

五、Composition API中的生命周期钩子

Vue 3的Composition API提供了对应的生命周期函数,名称前加"on":

选项式APIComposition API
beforeCreate无直接对应 (使用setup())
created无直接对应 (使用setup())
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted
activatedonActivated
deactivatedonDeactivated
errorCapturedonErrorCaptured

使用示例

import { onMounted, onUpdated, onUnmounted } from 'vue'

export default {
  setup() {
    onMounted(() => {
      console.log('组件已挂载')
    })
    
    onUpdated(() => {
      console.log('组件已更新')
    })
    
    onUnmounted(() => {
      console.log('组件已卸载')
    })
  }
}

六、生命周期钩子的最佳实践

  1. 数据请求:通常在created或mounted中进行,如果数据不需要依赖DOM则在created中请求更早

  2. DOM操作:必须在mounted或之后的生命周期中进行

  3. 清理工作:在beforeUnmount中清理定时器、事件监听器等资源

  4. 避免在updated中修改状态:可能导致无限循环更新

  5. 异步操作:使用$nextTick确保DOM更新完成

  6. 组合式API:在setup()中注册生命周期函数时,确保同步注册

七、常见问题

  1. created和mounted的区别

    • created:数据已初始化,但DOM未生成
    • mounted:DOM已生成,可操作DOM
  2. 为什么beforeCreate中无法访问data

    • 此时数据观测尚未初始化
  3. 异步组件生命周期

    • 异步组件的加载有额外的生命周期:onBeforeRouteUpdate
  4. Vue 2到Vue 3的生命周期变化

    • beforeDestroybeforeUnmount
    • destroyedunmounted
http://www.dtcms.com/a/113440.html

相关文章:

  • 记录_文件操作
  • C# 程序脱壳,去除强签名StrongNameRemove
  • python加载训练好的模型并进行叶片实例分割预测
  • B树和B+树的区别(B Tree B+ Tree)
  • Windows扫描功能在哪?如何打开?如何使用自带的扫描程序进行扫描
  • Python实现ssh自动连接
  • 对比学习中的NCE(Noise-Contrastive Estimation)和InfoNCE(SimCLR)损失函数+案例(附SimSiam分析)
  • C-S模式之实现一对一聊天
  • 【MATLAB第113期】基于MATLAB的EFAST扩展傅里叶幅度敏感性分析方法(有目标函数)
  • Linux 下 日志系统搭建全攻略
  • 【算法】滑动窗口
  • 使用 ResUNet++、增强对结直肠息肉分割的图像识别综合研究
  • 【嵌入式学习5】PyQt5注册界面 - 自定义信号和槽
  • Unity:Simple Follow Camera(简单相机跟随)
  • 讯飞语音听写(流式版)开发指南
  • BMC PSL function(42)-floor()
  • 第四章 react-redux,@reduxjs/toolkit依赖,学习
  • MySQL慢查询日志通俗指南
  • Java三大循环结构深度解析:从入门到精通的实践指南
  • 一.数据库基础知识
  • 大衣的旅行--前缀和+二分
  • 特殊的质数肋骨--dfs+isp
  • Python----TensorFlow(TensorFlow介绍,安装,主要模块,高级功能)
  • esp32cam 开发板搭载ov3660摄像头在arduino中调用kimi进行图像识别
  • 【Unity】导入资源shader报错
  • Latex入门之超详细的Latex环境配置教程
  • 7-1 素数求和(线性筛实现)
  • python | 获取字符串中某个字符的所有位置:find(),enumerate(),re.finditer,index()
  • JSON介绍及使用
  • MathType安装