面试官 : “ 说一下 Vue 的 8 个生命周期钩子都做了什么 ? ”

一、Vue3 8 个核心生命周期钩子(按执行顺序)

阶段 选项式 API 名称 组合式 API 名称 执行时机 核心作用 & 实战场景
初始化阶段 beforeCreate 无(setup 替代) 实例创建前,数据 / 方法未初始化,this 不可用 Vue2 中用于初始化非响应式数据;Vue3 中逻辑移到 setup 最顶部(无响应式操作)
初始化阶段 created 无(setup 替代) 实例创建完成,数据 / 方法已初始化,DOM 未生成 1. 发起异步请求(接口请求);2. 初始化非 DOM 相关逻辑(如数据格式化)
挂载阶段 beforeMount onBeforeMount 挂载开始前,模板编译完成,DOM 未挂载到页面($el 未生成) 1. 预操作 DOM 结构(如计算 DOM 尺寸,需结合 nextTick);2. 初始化第三方库(挂载前准备)
挂载阶段 mounted onMounted DOM 挂载完成($el 已挂载),页面可见 1. 操作真实 DOM(如初始化 ECharts / 地图);2. 发起依赖 DOM 的异步请求;3. 监听 DOM 事件
更新阶段 beforeUpdate onBeforeUpdate 数据更新后,DOM 重新渲染前 1. 获取更新前的 DOM 状态(如旧输入框值);2. 取消不必要的监听 / 定时器(避免重复执行)
更新阶段 onUpdated onUpdated DOM 重新渲染完成,页面已更新 1. 获取更新后的 DOM 状态;2. 重新计算 DOM 相关数据(如滚动位置重置)
卸载阶段 beforeUnmount onBeforeUnmount 组件卸载前(实例仍可用,DOM 未销毁) 1. 清理副作用(清除定时器 / 事件监听);2. 销毁第三方库实例(如 ECharts 销毁)
卸载阶段 unmounted onUnmounted 组件卸载完成,DOM 销毁,实例失效 1. 最终清理(如取消接口请求);2. 释放内存(清空大型数组 / 对象引用)

二、关键细节(Vue3 核心变化)

1. setup 替代 beforeCreate/created

Vue3 中 setup 执行时机 = beforeCreate + created,这两个钩子在组合式 API 中被废弃,所有初始化逻辑直接写在 setup 中:

以下是 Vue3 生命周期钩子的完整可运行代码示例 ,包含选项式 API组合式 API(<script setup> 推荐写法) 两种风格,附带详细注释和实战场景(如接口请求、DOM 操作、定时器清理等),可直接复制到 Vue3 项目中运行。

三、组合式 API 示例(<script setup> 推荐)

Vue3 生命周期演示

xml 复制代码
<template>
  <div class="life-cycle-demo">
    <h3>Vue3 生命周期演示(组合式 API)</h3>
    <!-- 绑定响应式数据,触发更新阶段 -->
    <p>当前计数:{{ count }}</p>
    <button @click="count++">点击更新计数(触发更新钩子)</button>
    <!-- 挂载 ECharts 示例 DOM -->
    <div id="chart" style="width: 300px; height: 200px; margin: 20px 0;"></div>
  </div>
</template>

<script setup>
import { 
  ref, 
  onBeforeMount, 
  onMounted, 
  onBeforeUpdate, 
  onUpdated, 
  onBeforeUnmount, 
  unmounted 
} from 'vue';
// 模拟 ECharts(实际需安装:npm install echarts)
import * as echarts from 'echarts';

// 🫱🫱🫱 1. setup 本身替代 beforeCreate + created(初始化阶段)
console.log('===== setup 执行(等价于 beforeCreate + created)=====');
// 响应式数据初始化
const count = ref(0);
// 模拟接口请求(created 阶段核心场景)
const fetchData = async () => {
  try {
    console.log('发起异步接口请求(created 阶段)');
    // 模拟接口延迟
    const res = await new Promise(resolve => {
      setTimeout(() => resolve({ data: '模拟接口返回数据' }), 1000);
    });
    console.log('接口请求完成:', res.data);
  } catch (err) {
    console.error('接口请求失败:', err);
  }
};
// 执行接口请求(等价于 created 中调用)
fetchData();

// 🫱🫱🫱 2. 挂载阶段:beforeMount(DOM 未挂载)
onBeforeMount(() => {
  console.log('===== onBeforeMount 执行 =====');
  console.log('DOM 未挂载,#chart 元素:', document.getElementById('chart')); // null
  // 若需提前操作 DOM,需结合 nextTick
});

// 🫱🫱🫱 3. 挂载阶段:mounted(DOM 已挂载,核心操作 DOM 场景)
let myChart = null;
onMounted(() => {
  console.log('===== onMounted 执行 =====');
  console.log('DOM 已挂载,#chart 元素:', document.getElementById('chart')); // 存在
  // 初始化 ECharts(依赖 DOM 的第三方库)
  myChart = echarts.init(document.getElementById('chart'));
  myChart.setOption({
    title: { text: '生命周期演示图表' },
    xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed'] },
    yAxis: { type: 'value' },
    series: [{ data: [120, 200, 150], type: 'bar' }]
  });
  // 模拟定时器(需在卸载阶段清理)
  const timer = setInterval(() => {
    console.log('定时器运行中(count:', count.value, ')');
  }, 1000);
  // 把定时器存到全局,方便卸载时清理
  window.lifeCycleTimer = timer;
});

// 🫱🫱🫱 4. 更新阶段:beforeUpdate(数据更新,DOM 未重新渲染)
onBeforeUpdate(() => {
  console.log('===== onBeforeUpdate 执行 =====');
  console.log('数据已更新(count:', count.value, '),DOM 未刷新');
  // 可获取更新前的 DOM 状态(如旧的图表数据)
});

// 🫱🫱🫱 5. 更新阶段:updated(DOM 已重新渲染)
onUpdated(() => {
  console.log('===== onUpdated 执行 =====');
  console.log('DOM 已更新(count:', count.value, ')');
  // 若数据更新后需重新渲染图表
  if (myChart) {
    myChart.setOption({
      series: [{ data: [120 + count.value * 10, 200 + count.value * 10, 150 + count.value * 10] }]
    });
  }
});

// 🫱🫱🫱 6. 卸载阶段:beforeUnmount(组件即将卸载,清理副作用)
onBeforeUnmount(() => {
  console.log('===== onBeforeUnmount 执行 =====');
  // 清理定时器
  clearInterval(window.lifeCycleTimer);
  // 销毁 ECharts 实例
  if (myChart) {
    myChart.dispose();
    myChart = null;
  }
  console.log('副作用已清理(定时器、ECharts 已销毁)');
});

// 🫱🫱🫱 7. 卸载阶段:unmounted(组件已完全卸载)
unmounted(() => {
  console.log('===== unmounted 执行 =====');
  console.log('组件已卸载,DOM 已销毁,实例失效');
});
</script>

四、选项式 API 示例(兼容 Vue2 写法)

xml 复制代码
<template>
  <div class="life-cycle-demo">
    <h3>Vue3 生命周期演示(选项式 API)</h3>
    <p>当前计数:{{ count }}</p>
    <button @click="count++">点击更新计数</button>
    <div id="chart" style="width: 300px; height: 200px; margin: 20px 0;"></div>
  </div>
</template>

<script>
import * as echarts from 'echarts';

export default {
  // 响应式数据
  data() {
    return {
      count: 0,
      myChart: null,
      timer: null
    };
  },

  // 🫱🫱🫱 1. 初始化阶段:beforeCreate(实例刚创建,数据/方法未初始化)
  beforeCreate() {
    console.log('===== beforeCreate 执行 =====');
    console.log('数据未初始化:', this.count); // undefined
    console.log('方法未初始化:', this.fetchData); // undefined
  },

  // 🫱🫱🫱 2. 初始化阶段:created(数据/方法已初始化,DOM 未生成)
  created() {
    console.log('===== created 执行 =====');
    console.log('数据已初始化:', this.count); // 0
    // 发起异步请求
    this.fetchData();
  },

  // 🫱🫱🫱 3. 挂载阶段:beforeMount(模板编译完成,DOM 未挂载)
  beforeMount() {
    console.log('===== beforeMount 执行 =====');
    console.log('DOM 未挂载,#chart 元素:', document.getElementById('chart')); // null
  },

  // 🫱🫱🫱 4. 挂载阶段:mounted(DOM 已挂载,可操作真实 DOM)
  mounted() {
    console.log('===== mounted 执行 =====');
    console.log('DOM 已挂载,#chart 元素:', document.getElementById('chart')); // 存在
    // 初始化 ECharts
    this.myChart = echarts.init(document.getElementById('chart'));
    this.myChart.setOption({
      title: { text: '选项式 API 图表' },
      xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed'] },
      yAxis: { type: 'value' },
      series: [{ data: [120, 200, 150], type: 'bar' }]
    });
    // 启动定时器
    this.timer = setInterval(() => {
      console.log('定时器运行中(count:', this.count, ')');
    }, 1000);
  },

  // 🫱🫱🫱 5. 更新阶段:beforeUpdate(数据更新,DOM 未重新渲染)
  beforeUpdate() {
    console.log('===== beforeUpdate 执行 =====');
    console.log('数据已更新(count:', this.count, '),DOM 未刷新');
  },

  // 🫱🫱🫱 6. 更新阶段:updated(DOM 已重新渲染)
  updated() {
    console.log('===== updated 执行 =====');
    console.log('DOM 已更新(count:', this.count, ')');
    // 重新渲染图表
    if (this.myChart) {
      this.myChart.setOption({
        series: [{ data: [120 + this.count * 10, 200 + this.count * 10, 150 + this.count * 10] }]
      });
    }
  },

  // 🫱🫱🫱 7. 卸载阶段:beforeUnmount(组件即将卸载,清理副作用)
  beforeUnmount() {
    console.log('===== beforeUnmount 执行 =====');
    // 清理定时器
    clearInterval(this.timer);
    // 销毁 ECharts
    if (this.myChart) {
      this.myChart.dispose();
      this.myChart = null;
    }
  },

  // 🫱🫱🫱 8. 卸载阶段:unmounted(组件已完全卸载)
  unmounted() {
    console.log('===== unmounted 执行 =====');
    console.log('组件已卸载,资源已清理');
  },

  // 自定义方法:模拟接口请求
  methods: {
    async fetchData() {
      try {
        console.log('发起接口请求(created 阶段)');
        const res = await new Promise(resolve => {
          setTimeout(() => resolve({ data: '选项式 API 接口数据' }), 1000);
        });
        console.log('接口请求完成:', res.data);
      } catch (err) {
        console.error('接口请求失败:', err);
      }
    }
  }
};
</script>

五、测试方式(验证生命周期执行)

  1. 挂载阶段 :页面加载后,控制台会依次打印 setup/beforeCreatecreatedbeforeMountmounted,同时 ECharts 图表渲染完成,定时器开始运行。

  2. 更新阶段 :点击 "点击更新计数" 按钮,触发 beforeUpdateupdated,图表数据随计数更新。

  3. 卸载阶段

    • 若使用路由,跳转到其他页面(组件卸载);
    • 或手动移除组件(如用 v-if 控制),控制台会打印 beforeUnmountunmounted,定时器停止,ECharts 实例销毁。

六、核心注意点

  1. 组合式 API 无 beforeCreate/created :所有初始化逻辑直接写在 <script setup> 顶部,等价于这两个钩子。
  2. 副作用必须清理 :定时器、事件监听、第三方库实例(如 ECharts)需在 onBeforeUnmount/beforeUnmount 中清理,避免内存泄漏。
  3. DOM 操作仅在 mounted/updated 中安全beforeMount 中操作 DOM 需结合 nextTick
  4. updated 中避免无限循环 :不要在 updated 中直接修改响应式数据(除非加条件判断)。

通过这个示例,你可以直观看到每个生命周期钩子的执行时机和实际用途,覆盖日常开发中 90% 以上的生命周期场景

相关推荐
清山博客21 小时前
OpenCV 人脸识别和比对工具
前端·webpack·node.js
要加油哦~21 小时前
AI | 实践教程 - ScreenCoder | 多agents前端代码生成
前端·javascript·人工智能
程序员Sunday1 天前
说点不一样的。GPT-5.3 与 Claude Opus 4.6 同时炸场,前端变天了?
前端·gpt·状态模式
yq1982043011561 天前
静思书屋:基于Java Web技术栈构建高性能图书信息平台实践
java·开发语言·前端
aPurpleBerry1 天前
monorepo (Monolithic Repository) pnpm rush
前端
青茶3601 天前
php怎么实现订单接口状态轮询请求
前端·javascript·php
鹏北海1 天前
micro-app 微前端项目部署指南
前端·nginx·微服务
发现一只大呆瓜1 天前
虚拟列表:从定高到动态高度的 Vue 3 & React 满分实现
前端·vue.js·react.js
css趣多多1 天前
add组件增删改的表单处理
java·服务器·前端
证榜样呀1 天前
2026 大专计算机专业必考证书推荐什么
大数据·前端