相较于Vue2,Vue3通过Composition API带来了更灵活的生命周期管理方式。通过onBeforeMount
等函数注册钩子时,实际是通过injectHook
方法将回调函数注册到组件实例的hmr
属性中。
在 Vue3 应用开发中,生命周期钩子函数扮演着至关重要的角色。它们允许开发者在组件从创建到销毁的各个阶段执行自定义逻辑,为开发者提供了对组件生命周期的精细控制能力。理解和熟练运用这些钩子函数,是开发高效、健壮 Vue3 应用的关键。
// Vue3源码片段(packages/runtime-core/src/apiLifecycle.ts)
export function injectHook(
type: LifecycleHook,
hook: Function & { __weh?: Function },
target: ComponentInternalInstance | null
) {
const hooks = target[type] || (target[type] = [])
hooks.push(hook)
}
data
、computed
、methods
等属性尚未初始化,无法访问 this
。beforeCreate
使用较少,但在一些需要在组件创建前执行通用逻辑的场景下,例如记录组件创建日志等操作,可在此处编写代码。data
、computed
、methods
等已初始化,可通过 this
访问组件的属性和方法,但 DOM 尚未挂载。<template>
<div>{{ message }}div>
template>
<script setup>
import { ref } from 'vue';
const message = ref('');
const fetchData = async () => {
const response = await fetch('/api/data');
const data = await response.json();
message.value = data.text;
};
fetchData();
script>
$el
访问真实的 DOM 元素,或使用 refs
访问子组件及元素。以ECharts集成示例:
<template>
<div ref="chartContainer">div>
template>
<script setup>
import { ref, onMounted } from 'vue';
import Chart from 'chart.js';
const chartContainer = ref(null);
onMounted(() => {
if (chartContainer.value) {
new Chart(chartContainer.value, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [
{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}
]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
}
});
script>
data
已经发生变化,但 DOM 尚未更新。updated
钩子函数中操作 DOM 时要避免陷入死循环,因为再次修改数据可能会再次触发更新。<template>
<div @click="updateData">
<p>{{ message }}p>
div>
template>
<script setup>
import { ref, onBeforeUpdate, onUpdated } from 'vue';
const message = ref('初始消息');
const updateData = () => {
message.value = '更新后的消息';
};
onBeforeUpdate(() => {
console.log('数据即将更新,当前消息:', message.value);
});
onUpdated(() => {
console.log('数据已更新,DOM 已重新渲染');
});
script>
<template>
<div>
<p>{{ message }}p>
div>
template>
<script setup>
import { ref, onBeforeUnmount, onUnmounted } from 'vue';
const message = ref('组件内容');
let timer;
const startTimer = () => {
timer = setInterval(() => {
console.log('定时器运行中');
}, 1000);
};
startTimer();
onBeforeUnmount(() => {
clearInterval(timer);
console.log('组件即将卸载,清除定时器');
});
onUnmounted(() => {
console.log('组件已卸载');
});
script>
问题现象 | 原因分析 | 解决方案 |
---|---|---|
mounted中获取DOM为null | 异步渲染延迟 | 使用nextTick() |
内存泄漏 | 未清理事件监听 | 建立清理函数注册表 |
重复请求 | 未取消前次请求 | 使用AbortController |
写在最后
哈喽!大家好呀,我是 Code_Cracke,一名热爱编程的小伙伴。在这里,我将分享一些实用的开发技巧和经验心得。如果你也对编程充满热情,欢迎关注并一起交流学习!
如果你对这篇文章有任何疑问、建议或者独特的见解,欢迎在评论区留言。无论是探讨技术细节,还是分享项目经验,都能让我们共同进步。