生命周期钩子

组合式 API 中的生命周期钩子

在 Vue3 的组合式 API 中,生命周期钩子函数被设计为可导入的函数,而不是选项式 API 中的方法。这些钩子函数需要在 setup() 函数中调用。

1. 生命周期钩子列表

Vue3 提供了以下生命周期钩子函数:

组合式 API 选项式 API 描述
onBeforeMount beforeMount 组件挂载前调用
onMounted mounted 组件挂载后调用
onBeforeUpdate beforeUpdate 组件更新前调用
onUpdated updated 组件更新后调用
onBeforeUnmount beforeUnmount 组件卸载前调用
onUnmounted unmounted 组件卸载后调用
onErrorCaptured errorCaptured 捕获子组件错误时调用
onRenderTracked - 组件渲染时追踪依赖
onRenderTriggered - 组件重新渲染时触发
onActivated - KeepAlive 组件激活时调用
onDeactivated - KeepAlive 组件停用时调用

2. 基本使用

在 setup() 函数中导入并使用生命周期钩子。

示例:使用生命周期钩子

<script setup>
import { 
  onBeforeMount, 
  onMounted, 
  onBeforeUpdate, 
  onUpdated, 
  onBeforeUnmount, 
  onUnmounted 
} from 'vue';

// 组件挂载前
onBeforeMount(() => {
  console.log('组件挂载前');
});

// 组件挂载后
onMounted(() => {
  console.log('组件挂载后');
  // 可以在这里进行 DOM 操作
  const element = document.getElementById('my-element');
  if (element) {
    element.textContent = 'Hello from mounted';
  }
});

// 组件更新前
onBeforeUpdate(() => {
  console.log('组件更新前');
});

// 组件更新后
onUpdated(() => {
  console.log('组件更新后');
  // 可以在这里获取更新后的 DOM
});

// 组件卸载前
onBeforeUnmount(() => {
  console.log('组件卸载前');
  // 清理资源,如事件监听器、定时器等
  clearInterval(timer);
});

// 组件卸载后
onUnmounted(() => {
  console.log('组件卸载后');
});

// 定时器示例
let timer;
onMounted(() => {
  timer = setInterval(() => {
    console.log('定时器执行');
  }, 1000);
});
onBeforeUnmount(() => {
  clearInterval(timer);
});
</script>

3. 错误捕获

使用 onErrorCaptured() 钩子可以捕获子组件的错误。

示例:捕获错误

<script setup>
import { onErrorCaptured } from 'vue';

onErrorCaptured((err, vm, info) => {
  console.log('捕获到错误:', err);
  console.log('错误组件:', vm);
  console.log('错误信息:', info);
  
  // 返回 true 可以阻止错误继续向上传播
  return false;
});
</script>

4. 渲染追踪

Vue3 提供了两个用于调试的生命周期钩子:

示例:渲染追踪

<script setup>
import { onRenderTracked, onRenderTriggered } from 'vue';

// 组件渲染时追踪依赖
onRenderTracked((event) => {
  console.log('渲染追踪:', event);
  // event 包含:
  // - key: 追踪的属性名
  // - target: 追踪的目标对象
  // - type: 追踪类型(getter, setter, ...)
});

// 组件重新渲染时触发
onRenderTriggered((event) => {
  console.log('渲染触发:', event);
  // event 包含:
  // - key: 触发更新的属性名
  // - target: 触发更新的目标对象
  // - type: 触发类型(setter, ...)
  // - newValue: 新值
  // - oldValue: 旧值
});
</script>

5. KeepAlive 相关钩子

当组件被 KeepAlive 包裹时,会触发 onActivated 和 onDeactivated 钩子。

示例:KeepAlive 钩子

<script setup>
import { onActivated, onDeactivated } from 'vue';

onActivated(() => {
  console.log('组件激活');
  // 可以在这里恢复状态
});

onDeactivated(() => {
  console.log('组件停用');
  // 可以在这里保存状态
});
</script>

6. 生命周期钩子的执行顺序

生命周期钩子的执行顺序如下:

  1. onBeforeMount
  2. onMounted
  3. onBeforeUpdate
  4. onUpdated
  5. onBeforeUnmount
  6. onUnmounted

7. 与选项式 API 混合使用

在 Vue3 中,可以混合使用组合式 API 和选项式 API 的生命周期钩子。

示例:混合使用生命周期钩子

<script>
import { onMounted } from 'vue';

export default {
  // 选项式 API 生命周期
  mounted() {
    console.log('选项式 API: mounted');
  },
  
  // 组合式 API 生命周期
  setup() {
    onMounted(() => {
      console.log('组合式 API: onMounted');
    });
  }
}
// 执行顺序:
// 组合式 API: onMounted
// 选项式 API: mounted
</script>

8. 生命周期钩子的最佳实践

  • 在 onMounted 中进行 DOM 操作和数据请求
  • 在 onBeforeUnmount 中清理资源,如事件监听器、定时器、WebSocket 连接等
  • 使用 onErrorCaptured 捕获和处理子组件的错误
  • 避免在生命周期钩子中进行过于复杂的计算
  • 合理使用 KeepAlive 相关钩子管理组件状态

9. 生命周期钩子的注意事项

  • 生命周期钩子必须在 setup() 函数中调用
  • 每个生命周期钩子可以多次调用,它们会按照注册顺序执行
  • onMounted 等钩子在服务器端渲染时不会执行
  • onErrorCaptured 只能捕获子组件的错误,不能捕获自身的错误