Vue3-生命周期

40 阅读2分钟

图片取自vue3官网教程:cn.vuejs.org/guide/essen…

生命周期.png

一个关键点是: <script setup> 本身就是在 beforeCreatecreated 阶段执行的

因此,在 <script setup> 中,没有 beforeCreatecreated 这两个钩子。在<script> 标签顶层编写的任何代码(比如定义变量、console.log)都可以看作是在 created 钩子中执行的。

组合式api中主要的6个生命周期钩子

以下是 <script setup> 中常用的生命周期钩子函数,按执行顺序列出:

  1. onBeforeMount

    • 时机: 在组件即将被挂载到 DOM 之前调用。此时,template 已经编译完成,但尚未渲染成真实的 DOM。
  2. onMounted

    • 时机: 在组件被挂载到 DOM 之后调用。此时,组件已经渲染完毕,你可以访问到真实的 DOM 元素。
  3. onBeforeUpdate

    • 时机: 当组件的响应式数据(如 refreactive)发生变化,即将触发 DOM 更新之前调用。
  4. onUpdated

    • 时机: 在组件的 DOM 更新完成之后调用。
  5. onBeforeUnmount

    • 时机: 在组件实例即将被卸载和销毁之前调用。此时组件功能仍然正常。
  6. onUnmounted

    • 时机: 在组件实例被卸载和销毁之后调用。

举个栗子

为了看到更新相关的钩子 (onBeforeUpdate, onUpdated),添加了一个按钮来改变一个响应式数据。卸载相关的钩子 (onBeforeUnmount, onUnmounted),需要在父组件中通过 v-if 来控制这个 LifecycleDemo 组件的显示和隐藏。

<template>
  <div class="lifecycle-demo">
    <h3>Vue 3 &lt;script setup&gt; 生命周期演示</h3>
    <p>
      当前计数值 (count): <strong>{{ count }}</strong>
    </p>
    <button @click="increment">增加 count</button>
    <p><i>打开浏览器的控制台查看生命周期日志。</i></p>
  </div>
</template>

<script setup lang="ts">
// 1. 导入所有需要的 API
import { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from 'vue';

// --- "created" 阶段 ---
// ( <script setup> 顶层的代码会在 "created" 之前执行)
console.log('--- 1. script setup ---');
console.log('组件正在被创建 (类似 "created")');

// 定义响应式数据
const count = ref(0);

const increment = () => {
  count.value++;
};

// --- 挂载阶段 ---
onBeforeMount(() => {
  console.log('--- 2. onBeforeMount ---');
  console.log('组件即将挂载,DOM 尚未创建。');
  console.log('count 值:', count.value);
});

onMounted(() => {
  console.log('--- 3. onMounted ---');
  console.log('组件已挂载,DOM 已创建。');
  // 此时可以安全地访问 DOM,例如:
  // const el = document.querySelector('.lifecycle-demo');
  // console.log('DOM 元素:', el);
});

// --- 更新阶段 ---
// (点击 "增加 count" 按钮时触发)
onBeforeUpdate(() => {
  console.log('--- 4. onBeforeUpdate ---');
  console.log('数据已更新,但 DOM 尚未更新。');
  console.log('即将更新的 count 值:', count.value);
});

onUpdated(() => {
  console.log('--- 5. onUpdated ---');
  console.log('DOM 已更新。');
  console.log('更新后的 count 值:', count.value);
});

// --- 卸载阶段 ---
// (当这个组件从父组件中被 v-if="false" 移除时触发)
onBeforeUnmount(() => {
  console.log('--- 6. onBeforeUnmount ---');
  console.log('组件即将卸载。');
  // 适合在此处清理定时器、事件监听器等
  // clearInterval(myTimer);
});

onUnmounted(() => {
  console.log('--- 7. onUnmounted ---');
  console.log('组件已卸载。');
});
</script>

<style scoped>
.lifecycle-demo {
  padding: 20px;
  border: 2px solid #42b983;
  border-radius: 8px;
  background-color: #f0f9f5;
}
button {
  margin-top: 10px;
  padding: 8px 12px;
  background-color: #42b983;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
button:hover {
  background-color: #36a476;
}
</style>

控制台输出顺序

  • 组件挂载

image.png

  • 点击按钮修改数据

image.png

  • 在父组件中控制组件切换

image.png