Skip to content

Vue.js 生命周期深入解析

生命周期流程图

graph TD
    A[创建组件实例] --> B[beforeCreate]
    B --> C[created]
    C --> D[beforeMount]
    D --> E[mounted]
    
    E --> F{数据更新?}
    F -->|是| G[beforeUpdate]
    G --> H[updated]
    H --> F
    
    F -->|否| I{组件卸载?}
    I -->|是| J[beforeUnmount]
    J --> K[unmounted]
    
    L[keep-alive] --> M[activated]
    L --> N[deactivated]
    
    O[错误产生] --> P[errorCaptured]

错误处理

flowchart TD
    A[子组件错误] --> B{errorCaptured}
    B -->|返回true| C[向上传播]
    B -->|返回false| D[停止传播]
    C --> E[全局错误处理]

选项式 API (Options API)

选项式 API 是 Vue 传统的组织组件代码的方式。我们通过定义一个包含选项的对象来描述组件的逻辑,例如 datamethodsmounted 等选项。属性定义在组件选项中,使用 this 访问。

javascript:019cf3a6-60da-47db-922c-a0b5bea053ae
export default {
    data() {
        return {
            count: 0
        }
    },
    methods: {
        increment() {
            this.count++
        }
    },
    mounted() {
        console.log('组件已挂载')
    }
}

组合式 API (Composition API)

组合式 API 是 Vue3 新增的一种组织组件代码的方式。它允许我们使用导入的 API 函数来描述组件逻辑。组件的代码是通过组合函数来组织的,通常在 setup 函数中编写。

javascript
import { ref, onMounted } from 'vue'

export default {
    setup() {
        const count = ref(0)
        
        function increment() {
            count.value++
        }
        
        onMounted(() => {
            console.log('组件已挂载')
        })
        
        return {
            count,
            increment
        }
    }
}

生命周期钩子对应关系

NOTE

Vue3提供两种编写方式,下表展示了它们的对应关系:

选项式 API组合式 API执行时机与用途
beforeCreatesetup()组件实例初始化之前,此时无法访问数据和方法
createdsetup()组件实例创建完成,可以访问数据和方法,但还未挂载DOM
beforeMountonBeforeMount()组件挂载之前,模板编译完成但还未渲染到页面
mountedonMounted()组件挂载完成,可以访问DOM,适合执行初始化操作
beforeUpdateonBeforeUpdate()数据更新时,DOM更新之前调用,适合在更新前访问现有DOM
updatedonUpdated()DOM更新完成后调用,注意避免在此修改数据防止死循环
beforeUnmountonBeforeUnmount()组件卸载前调用,适合清理工作(定时器、事件监听等)
unmountedonUnmounted()组件卸载完成后调用,组件完全销毁
errorCapturedonErrorCaptured()捕获后代组件错误,可以处理错误并阻止向上传播
renderTrackedonRenderTracked()调试用:跟踪虚拟DOM重新渲染的依赖来源
renderTriggeredonRenderTriggered()调试用:跟踪触发虚拟DOM重新渲染的依赖
activatedonActivated()keep-alive缓存的组件激活时调用
deactivatedonDeactivated()keep-alive缓存的组件停用时调用
serverPrefetchonServerPrefetch()服务端渲染期间调用,用于预获取数据

特别说明

  1. setup 函数的特殊性:

    • 在组件创建之前执行,因此替代了 beforeCreate 和 created
    • 没有 this 上下文
    • 返回的对象中的属性将暴露给模板使用
    • 可以是异步函数(setup async)
  2. 调试钩子的使用场景:

    • onRenderTracked
      • 跟踪组件首次渲染时的依赖收集
      • 帮助理解哪些响应式数据被组件使用
    • onRenderTriggered
      • 跟踪导致组件重新渲染的具体依赖
      • 帮助排查性能问题和不必要的渲染
  3. 组合式 API 的最佳实践:

    • 使用组合函数(Composables)抽取和复用逻辑
    • 保持 setup 函数的简洁
    • 合理使用生命周期钩子
    • 注意及时清理副作用
    • 使用 TypeScript 获得更好的类型支持
  4. 性能考虑:

    • 组合式 API 通常能产生更好的 tree-shaking 效果
    • 代码更容易被压缩
    • 按需导入可以减少打包体积

挂载阶段钩子函数

挂载阶段

sequenceDiagram
    participant App as 应用
    participant VM as 虚拟DOM
    participant DOM as 真实DOM
    
    App->>VM: beforeMount
    VM->>DOM: 创建DOM元素
    DOM->>App: mounted

onBeforeMount 与 beforeMount

组件挂载到 DOM 之前被调用。此时模板已经编译完成,但还没有渲染到页面上。

javascript
// 选项式 API
export default {
   beforeMount() {
       console.log('组件即将挂载');
   }

// 组合式 API
import { onBeforeMount } from 'vue';
setup() {
   onBeforeMount(() => {
       console.log('组件即将挂载');
   })

onMounted 与 mounted

组件挂载到 DOM 后调用。这是最常用的生命周期之一,通常用于: 访问或操作 DOM 发起初始化数据请求 添加事件监听器

javascript
// 选项式 API
export default {
   mounted() {
       console.log('组件已挂载');
       this.fetchData();
   }
}

// 组合式 API
import { onMounted } from 'vue';
setup() {
   onMounted(() => {
       console.log('组件已挂载');
       fetchData();
   })
}

更新阶段钩子函数

onBeforeUpdate 与 beforeUpdate

数据发生改变后,DOM 被更新之前调用。适合在现有 DOM 将要被更新之前访问它。

javascript
// 选项式 API
export default {
   beforeUpdate() {
       console.log('DOM更新之前');
   }

// 组合式 API
import { onBeforeUpdate } from 'vue';
setup() {
   onBeforeUpdate(() => {
       console.log('DOM更新之前');
   })

onUpdated 与 updated

数据更改导致的虚拟 DOM 重新渲染和打补丁之后调用。 意:不要在 updated 中修改数据,可能会导致无限循环。

javascript
// 选项式 API
export default {
   updated() {
       console.log('DOM更新完成');
   }

// 组合式 API
import { onUpdated } from 'vue';
setup() {
   onUpdated(() => {
       console.log('DOM更新完成');
   })

卸载阶段钩子函数

onBeforeUnmount 与 beforeUnmount

组件卸载之前调用。这个阶段组件实例仍然完全可用。 用于: 清除定时器 取消事件监听 取消网络请求

javascript
// 选项式 API
export default {
   beforeUnmount() {
       console.log('组件即将卸载');
       clearInterval(this.timer);
   }

// 组合式 API
import { onBeforeUnmount } from 'vue';
setup() {
   onBeforeUnmount(() => {
       console.log('组件即将卸载');
       clearInterval(timer);
   })

onUnmounted 与 unmounted

件卸载后调用。此时所有的子组件也都已经被卸载。

javascript
// 选项式 API
export default {
   unmounted() {
       console.log('组件已卸载');
   }

// 组合式 API
import { onUnmounted } from 'vue';
setup() {
   onUnmounted(() => {
       console.log('组件已卸载');
   })

beforeDestroy 与 destroyed

是 Vue 2.x 的生命周期函数,在 Vue 3 中已被重命名为 beforeUnmount 和 unmounted。

错误处理钩子函数

onErrorCaptured 与 errorCaptured

捕获到后代组件的错误时调用。可以返回 false 以阻止错误继续向上传播。

javascript
// 选项式 API
export default {
   errorCaptured(err, instance, info) {
       console.log('捕获到错误:', err);
       return false; // 阻止错误继续传播
   }

// 组合式 API
import { onErrorCaptured } from 'vue';
setup() {
   onErrorCaptured((err, instance, info) => {
       console.log('捕获到错误:', err);
       return false;
   })

调试钩子函数

onRenderTracked 与 renderTracked

试用的钩子,当组件渲染过程中追踪到响应式依赖时调用。

javascript
setup() {
   onRenderTracked((event) => {
       console.log('响应式依赖被追踪:', event);
   })

onRenderTriggered 与 renderTriggered

试用的钩子,当响应式依赖触发组件重新渲染时调用。

javascript
setup() {
   onRenderTriggered((event) => {
       console.log('触发组件重新渲染:', event);
   })

keep-alive 相关钩子函数

onActivated 与 activated

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

javascript
setup() {
   onActivated(() => {
       console.log('组件被激活');
   })

onDeactivated 与 deactivated

keep-alive 缓存的组件停用时调用。

javascript
setup() {
   onDeactivated(() => {
       console.log('组件被停用');
   })

服务端渲染钩子函数

onServerPrefetch 与 serverPrefetch

务端渲染期间,在实例渲染之前调用。常用于确保服务端渲染时数据已准备就绪。

javascript
etup() {
   onServerPrefetch(async () => {
       // 在服务端渲染期间等待异步数据
       await fetchServerData();
   })

实践建议

  1. 资源清理
  • beforeUnmount/onBeforeUnmount 中清理:
    • 定时器 (clearTimeout/clearInterval)
    • 事件监听器 (removeEventListener)
    • DOM 观察器 (disconnect)
    • 网络请求取消
    • WebSocket 连接关闭
  1. 数据更新
  • 避免在 updated/onUpdated 中直接修改响应式数据
  • 防止进入无限更新循环
  • 如需修改,请使用计算属性或监听器
  1. 错误处理
  • 合理使用 errorCaptured/onErrorCaptured 捕获子组件错误
  • 可以返回 false 阻止错误继续向上传播
  • 配合错误边界组件使用
  1. 性能优化
  • 调试钩子 (onRenderTracked/onRenderTriggered) 仅在开发环境使用
  • 用于分析组件重新渲染的原因
  • 帮助识别不必要的更新
  1. 缓存组件
  • 使用 keep-alive 时注意处理 activated/onActivated 钩子
  • 可以在 deactivated/onDeactivated 中暂停一些操作