Vue3 生命周期钩子

生命周期流程图

开始

│

├─ 初始化阶段

│ │

│ ├─ setup() 🔵 Composition API入口

│ │

│ └─ beforeCreate() 🟡 Options API(组合式API中不存在)

│ │

│ └─ created() 🟡 Options API(组合式API中不存在)

│

├─ 挂载阶段

│ │

│ ├─ onBeforeMount() ⚪ 挂载前

│ │

│ ├─ 编译模板

│ │

│ ├─ 创建虚拟DOM

│ │

│ ├─ 挂载到真实DOM

│ │

│ └─ onMounted() ✅ 挂载完成

│

├─ 更新阶段

│ │

│ ├─ onBeforeUpdate() 🔄 更新前

│ │

│ ├─ 重新渲染虚拟DOM

│ │

│ ├─ 打补丁(DOM更新)

│ │

│ └─ onUpdated() ✅ 更新完成

│

├─ 卸载阶段

│ │

│ ├─ onBeforeUnmount() ⚠️ 卸载前

│ │

│ ├─ 移除DOM元素

│ │

│ └─ onUnmounted() ❌ 卸载完成

│

└─ 缓存组件特殊阶段(keep-alive)

│

├─ onActivated() 🔄 激活时

│

└─ onDeactivated() 💤 停用时

一、生命周期钩子对照表

Options API Composition API 调用时机 常用场景
beforeCreate ❌ 无对应 实例初始化后,数据观测/事件配置前 极少使用
created ❌ 无对应 实例创建完成,数据观测/事件配置完成 Options API 中用于数据初始化
beforeMount onBeforeMount 挂载开始之前 服务端渲染中获取数据
mounted onMounted 挂载完成后 DOM操作、数据请求、定时器、事件监听
beforeUpdate onBeforeUpdate 数据更新,DOM 重新渲染前 获取更新前的DOM状态
updated onUpdated 数据更新,DOM 重新渲染后 DOM依赖操作、第三方库初始化
beforeDestroy (Vue 2) onBeforeUnmount 实例销毁前 清理定时器、取消订阅、解绑事件
destroyed (Vue 2) onUnmounted 实例销毁后 极少使用
activated onActivated keep-alive 组件激活时 恢复数据、重新请求
deactivated onDeactivated keep-alive 组件停用时 暂停定时器、保存状态

二、组合式API用法详解

2.1 基本使用

javascript 复制代码
<script setup>
import { 
  onBeforeMount,
  onMounted,
  onBeforeUpdate,
  onUpdated,
  onBeforeUnmount,
  onUnmounted,
  onActivated,
  onDeactivated,
  ref 
} from 'vue'

const count = ref(0)

// 1. 挂载阶段
onBeforeMount(() => {
  console.log('1. onBeforeMount - 挂载前')
  // 此时组件尚未挂载到DOM
  console.log('DOM元素:', document.querySelector('.app')) // null
})

onMounted(() => {
  console.log('2. onMounted - 挂载完成')
  // ✅ 最佳实践:
  // - DOM操作(获取元素、初始化图表等)
  // - 发起数据请求
  // - 设置定时器
  // - 添加事件监听
  
  const el = document.querySelector('.app')
  console.log('DOM元素:', el) // 真实DOM
  
  // 示例:初始化图表
  // initChart()
  
  // 示例:请求数据
  // fetchData()
  
  // 示例:开始定时器
  // timer = setInterval(() => {}, 1000)
  
  // 示例:监听窗口大小变化
  // window.addEventListener('resize', handleResize)
})

// 2. 更新阶段
onBeforeUpdate(() => {
  console.log('3. onBeforeUpdate - 更新前')
  console.log('count更新前的值:', count.value)
  
  // 可以获取更新前的DOM状态
  const el = document.querySelector('.count')
  console.log('更新前文本:', el?.textContent)
})

onUpdated(() => {
  console.log('4. onUpdated - 更新完成')
  console.log('count更新后的值:', count.value)
  
  // ⚠️ 注意事项:
  // 1. 避免在updated中修改响应式数据,可能导致无限循环
  // 2. 确保DOM更新已经完成
  
  // ✅ 适用场景:
  // - 第三方库需要基于DOM初始化
  // - 获取更新后的DOM尺寸
  
  // 示例:重新初始化第三方库
  // if (chartInstance) {
  //   chartInstance.dispose()
  //   initChart()
  // }
})

// 3. 卸载阶段
onBeforeUnmount(() => {
  console.log('5. onBeforeUnmount - 卸载前')
  
  // ✅ 必须清理!防止内存泄漏
  // - 清除定时器
  // - 取消事件监听
  // - 清理全局状态
  // - 取消网络请求
  
  // 示例:清理定时器
  // if (timer) clearInterval(timer)
  
  // 示例:移除事件监听
  // window.removeEventListener('resize', handleResize)
  
  // 示例:取消未完成的请求
  // if (currentRequest) currentRequest.abort()
})

onUnmounted(() => {
  console.log('6. onUnmounted - 卸载完成')
  // 此时组件实例已完全销毁
  // 可用于记录日志或清理全局资源
})

// 4. keep-alive 相关
onActivated(() => {
  console.log('激活组件')
  // 组件从缓存中激活时调用
  // 恢复数据、重新开始定时器等
  
  // 示例:恢复定时器
  // if (timerPaused) {
  //   startTimer()
  //   timerPaused = false
  // }
})

onDeactivated(() => {
  console.log('停用组件')
  // 组件被缓存时调用
  // 暂停定时器、保存状态等
  
  // 示例:暂停定时器
  // pauseTimer()
  // timerPaused = true
})
</script>

<template>
  <div class="app">
    <div class="count">Count: {{ count }}</div>
    <button @click="count++">增加</button>
  </div>
</template>

2.2 执行顺序示例

javascript 复制代码
<!-- ParentComponent.vue -->
<script setup>
import ChildComponent from './ChildComponent.vue'
import { onMounted, ref } from 'vue'

const showChild = ref(true)

onMounted(() => {
  console.log('父组件 mounted')
})
</script>

<template>
  <div>
    <button @click="showChild = !showChild">切换子组件</button>
    <ChildComponent v-if="showChild" />
  </div>
</template>

<!-- ChildComponent.vue -->
<script setup>
import { onMounted, onUnmounted } from 'vue'

onMounted(() => {
  console.log('子组件 mounted')
})

onUnmounted(() => {
  console.log('子组件 unmounted')
})
</script>

<!-- 执行顺序:
1. 父组件 setup
2. 子组件 setup
3. 子组件 onMounted
4. 父组件 onMounted
5. 切换时:子组件 onUnmounted
-->

三、Options API 生命周期

javascript 复制代码
<script>
export default {
  data() {
    return {
      count: 0
    }
  },
  
  // 1. 初始化阶段(在 Composition API 中被 setup 替代)
  beforeCreate() {
    console.log('beforeCreate')
    // 此时:data未初始化,methods未定义
    // console.log(this.count) // undefined
  },
  
  created() {
    console.log('created')
    // ✅ 可以访问:data、methods、computed
    // ❌ 不能访问:DOM($el)
    // 用途:数据初始化、API请求(服务端渲染)
    
    console.log(this.count) // 0
    console.log(this.$el)   // undefined
  },
  
  // 2. 挂载阶段
  beforeMount() {
    console.log('beforeMount')
    // 模板编译完成,但尚未挂载到DOM
    console.log(this.$el) // undefined 或 编译前的模板
  },
  
  mounted() {
    console.log('mounted')
    // 与组合式API的onMounted用途相同
    this.$nextTick(() => {
      // 确保DOM已完全更新
    })
  },
  
  // 3. 更新阶段
  beforeUpdate() {
    console.log('beforeUpdate')
  },
  
  updated() {
    console.log('updated')
    // 小心:不要在这里修改数据,可能导致循环
  },
  
  // 4. 卸载阶段(Vue 2 命名)
  beforeDestroy() {  // Vue 3 中仍可用,但建议用 beforeUnmount
    console.log('beforeDestroy')
  },
  
  destroyed() {      // Vue 3 中仍可用,但建议用 unmounted
    console.log('destroyed')
  },
  
  // 5. keep-alive 相关
  activated() {
    console.log('activated')
  },
  
  deactivated() {
    console.log('deactivated')
  },
  
  // 6. 错误处理(Vue 2.5+)
  errorCaptured(err, instance, info) {
    console.error('错误捕获:', err)
    // 可以返回 false 阻止错误继续向上传播
    return false
  }
}
</script>

四、生命周期使用统计

根据实际项目经验,各生命周期使用频率:

  1. 高频使用 (80% 场景):

    • onMounted - DOM操作、数据请求、事件监听

    • onUnmounted - 清理工作

  2. 中频使用 (15% 场景):

    • onUpdated - 第三方库集成

    • onBeforeUnmount - 确保清理

  3. 低频使用 (5% 场景):

    • onBeforeMount - 服务端渲染特殊需求

    • onBeforeUpdate - 特定优化场景

    • onActivated/onDeactivated - 使用 keep-alive 时

相关推荐
不可能片场29 分钟前
Electron 发布 cookie 库先查明文再写解密
前端·electron
郭小李33 分钟前
springmvc 拦截器
java·开发语言·前端
程序员大阳33 分钟前
副队长JavaScript教程(60)-BOM 初识:window 对象与浏览器模型
javascript·bom·window对象·浏览器模型
web打印社区34 分钟前
Chrome-kiosk-printing能上生产吗
开发语言·前端·javascript·chrome·websocket
白帽攻防录36 分钟前
某pc客户端app从xss到rce实战案例
前端·网络安全·黑客·xss·rce·src漏洞·app漏洞
潇小墨37 分钟前
我给自己造了一个桌面效率助手:剪贴板、截图提单、全盘文件搜索,全都塞进快捷键里
vue.js
志尊宝1 小时前
AI原生前端开发(041):AI辅助的状态管理(Zustand/Pinia)
前端·javascript·ai-native
修炼的dance1 小时前
pngquant 两档质量后接 oxipng,每步省多少花几秒
前端
费曼学习法1 小时前
无人值守AI内容矩阵实战(10):Windows 无 systemd,进程存活率 99% 怎么做
前端
Geoffwo1 小时前
DSH-SKILL基础
javascript