Vue 组件实例生命周期
每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤,比如设置好数据侦听,编译模板,挂载实例到 DOM,以及在数据改变时更新 DOM。在此过程中,它也会运行被称为生命周期钩子的函数,让开发者有机会在特定阶段运行自己的代码。
调用生命周期钩子API 都应该在组件的 setup()
阶段被同步调用。
这并不意味着对生命周期钩子API 的调用必须放在 setup() 或 <script setup>
内的词法上下文中。也可以在一个外部函数中调用,只要调用栈是同步的,且最终起源自 setup()
就可以。
生命周期钩子概述
在 Vue 3 中,组合式 API 提供了一系列的生命周期钩子函数,这些函数可以在组件的不同生命周期阶段执行特定的逻辑。
- onBeforeMount:在组件挂载到 DOM 之前调用。
- onMounted:在组件挂载到 DOM 之后调用。
- onBeforeUpdate:在组件更新之前调用。
- onUpdated:在组件更新之后调用。
- onBeforeUnmount:在组件卸载之前调用。
- onUnmounted:在组件卸载之后调用。
生命周期钩子的使用
1. onBeforeMount
onBeforeMount
钩子在组件挂载到 DOM 之前调用。可以在这个钩子中执行一些初始化逻辑,但此时 DOM 还没有被渲染。
<script setup>
import { onBeforeMount } from 'vue';
onBeforeMount(() => {
console.log('Component is about to be mounted');
});
</script>
2. onMounted
onMounted
钩子在组件挂载到 DOM 之后调用。此时,DOM 已经被渲染,可以在这个钩子中执行与 DOM 相关的操作,例如获取 DOM 元素、添加事件监听等。
<script setup>
import { onMounted } from 'vue';
onMounted(() => {
console.log('Component has been mounted');
const element = document.getElementById('my-element');
console.log(element);
});
</script>
3. onBeforeUpdate
onBeforeUpdate
钩子在组件更新之前调用。可以在这个钩子中执行一些准备工作,例如保存当前状态,以便在更新后进行比较。
<script setup>
import { onBeforeUpdate } from 'vue';
onBeforeUpdate(() => {
console.log('Component is about to be updated');
});
</script>
4. onUpdated
onUpdated
钩子在组件更新之后调用。此时,DOM 已经被更新,可以在这个钩子中执行与更新后的 DOM 相关的操作。
<script setup>
import { onUpdated } from 'vue';
onUpdated(() => {
console.log('Component has been updated');
});
</script>
5. onBeforeUnmount
onBeforeUnmount
钩子在组件卸载之前调用。可以在这个钩子中执行一些清理工作,例如移除事件监听、取消订阅等。
<script setup>
import { onBeforeUnmount } from 'vue';
onBeforeUnmount(() => {
console.log('Component is about to be unmounted');
});
</script>
6. onUnmounted
onUnmounted
钩子在组件卸载之后调用。此时,组件已经从 DOM 中移除,可以在这个钩子中执行一些最终的清理工作。
<script setup>
import { onUnmounted } from 'vue';
onUnmounted(() => {
console.log('Component has been unmounted');
});
</script>
示例
以下是一个综合示例,展示了如何在一个组件中使用多个生命周期钩子:
<template>
<div>
<p>{{ message }}</p>
<button @click="updateMessage">Update Message</button>
</div>
<div>
<button @click="toggleComponent">Toggle Component</button>
<component :is="currentComponent" />
</div>
</template>
<script setup>
import { shallowRef, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from 'vue';
import ComponentA from './components/ComponentA.vue';
import ComponentB from './components/ComponentB.vue';
const currentComponent = shallowRef(ComponentA);
const toggleComponent = () => {
currentComponent.value = currentComponent.value === ComponentA ? ComponentB : ComponentA;
};
const message = shallowRef('Hello, World!');
const updateMessage = () => {
message.value = 'Hello, Vue 3!';
};
// 在组件挂载之前调用
onBeforeMount(() => {
console.log('Component is about to be mounted');
});
// 在组件挂载之后调用
onMounted(() => {
console.log('Component has been mounted');
});
// 在组件更新之前调用
onBeforeUpdate(() => {
console.log('Component is about to be updated');
});
// 在组件更新之后调用
onUpdated(() => {
console.log('Component has been updated');
});
// 在组件卸载之前调用
onBeforeUnmount(() => {
console.log('Component is about to be unmounted');
});
// 在组件卸载之后调用
onUnmounted(() => {
console.log('Component has been unmounted');
});
</script>
<style scoped>
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
</style>
ComponentA.vue
<template>
<div>
<p>Component A</p>
</div>
</template>
<script setup>
import { onBeforeUnmount, onUnmounted } from 'vue';
onBeforeUnmount(() => {
console.log('Component A is about to be unmounted');
});
onUnmounted(() => {
console.log('Component A has been unmounted');
});
</script>
ComponentB.vue
<template>
<div>
<p>Component B</p>
</div>
</template>
<script setup>
import { onBeforeUnmount, onUnmounted } from 'vue';
onBeforeUnmount(() => {
console.log('Component B is about to be unmounted');
});
onUnmounted(() => {
console.log('Component B has been unmounted');
});
</script>
初始状态下,ComponentA
被渲染。
点击按钮切换到 ComponentB
,此时 ComponentA
将被卸载,触发 onBeforeUnmount
和 onUnmounted
钩子。
再次点击按钮切换回 ComponentA
,此时 ComponentB
将被卸载,触发 onBeforeUnmount
和 onUnmounted
钩子。