Vue 文档解读(一): 生命周期与钩子函数
相信大家对 Vue 的使用应该很熟悉了,那大家在使用 Vue 的一些钩子函数时,是否对其底层的原理知晓呢?如Vue的生命周期,以及浏览器中 DOM 树的形成及网页的渲染过程呢?这些都是 Vue 很基础的原理,以及面试的常考点。因此,本文将详细讲解 Vue 生命周期与 DOM 树形成、网页渲染的关系,帮助大家全面理解 Vue 是如何在浏览器中形成网页的。
浏览器渲染流程概述
在探讨 Vue 生命周期与网页渲染的关系之前,先了解一下浏览器渲染流程:
-
解析 HTML:浏览器解析 HTML 文档,生成 DOM 树。
-
解析 CSS:解析 CSS,生成 CSSOM 树。
-
构建渲染树:将 DOM 树和 CSSOM 树结合,生成渲染树。
-
布局:计算渲染树每个节点的布局(位置和大小)。
-
绘制:将渲染树的节点绘制到屏幕上。
DOM 树如下图所示:
什么是 Vue 生命周期
Vue 组件从创建到销毁的过程中,会经历一系列的初始化、渲染、更新和销毁的过程,这就是组件的生命周期。Vue 提供了一些钩子函数,让开发者在组件的不同阶段执行特定的操作。
Vue 生命周期钩子函数
Vue 生命周期钩子函数按顺序可以分为以下几个阶段:
-
创建阶段 (Creation)
onBeforeMount
onMounted
-
更新阶段 (Updating)
onBeforeUpdate
onUpdated
-
销毁阶段 (Destruction)
onBeforeUnmount
onUnmounted
-
错误处理
onErrorCaptured
-
渲染处理
onRenderTracked
onRenderTriggered
-
激活/停用
onActivated
onDeactivated
-
服务端预取
onServerPrefetch
Vue 生命周期与 DOM 树形成及网页渲染的关系
每个生命周期钩子函数在 Vue 组件的不同阶段被调用,与浏览器的 DOM 树形成和网页渲染过程紧密相关。下面将详细解释一些常用的钩子函数:
创建阶段
onBeforeMount
在挂载开始之前被调用。此时组件还未挂载到 DOM,虚拟 DOM 已生成。
import { onBeforeMount } from 'vue';
onBeforeMount(() => { console.log('onBeforeMount: 挂载开始之前被调用'); });
onMounted
在组件挂载到 DOM 后立即调用。适合在此进行 DOM 操作或数据请求。
import { onMounted } from 'vue';
onMounted(() => { console.log('onMounted: 组件挂载到 DOM 后被调用'); });
在这个阶段,浏览器将解析 HTML 并生成初始的 DOM 树。Vue 将模板编译成虚拟 DOM,并将其挂载到实际的 DOM 树上,浏览器完成首次渲染。
更新阶段
onBeforeUpdate
在数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。
import { onBeforeUpdate } from 'vue';
onBeforeUpdate(() => { console.log('onBeforeUpdate: 数据更新时被调用'); });
onUpdated
在由于数据更改导致的虚拟 DOM 重新渲染和打补丁之后调用。适合在此进行依赖于 DOM 更新的操作。
import { onUpdated } from 'vue';
onUpdated(() => { console.log('onUpdated: 虚拟 DOM 重新渲染和打补丁之后被调用'); });
当组件的数据发生变化时,Vue 会重新计算虚拟 DOM,并将其与上一次的虚拟 DOM 进行比较,找出变化的部分,然后更新实际的 DOM 树。这一过程称为打补丁(patching)。浏览器会重新计算渲染树,并重新布局和绘制页面。
销毁阶段
onBeforeUnmount
在实例销毁之前调用。适合在此进行清理操作,如移除事件监听器或清除定时器。
import { onBeforeUnmount } from 'vue';
onBeforeUnmount(() => { console.log('onBeforeUnmount: 实例销毁之前被调用'); });
onUnmounted
在实例销毁之后调用。所有事件监听器会被移除,所有子实例也会被销毁。
import { onUnmounted } from 'vue';
onUnmounted(() => { console.log('onUnmounted: 实例销毁之后被调用'); });
在这个阶段,Vue 会移除组件的所有绑定和事件监听器,并从 DOM 树中移除组件的根元素。浏览器会更新 DOM 树,并重新计算渲染树和布局。
激活/停用
onActivated
在 keep-alive 组件激活时调用。
import { onActivated } from 'vue';
onActivated(() => { console.log('onActivated: 组件被激活'); });
onDeactivated
在 keep-alive 组件停用时调用。
import { onDeactivated } from 'vue';
onDeactivated(() => { console.log('onDeactivated: 组件被停用'); });
错误处理
onErrorCaptured
当捕获一个来自子孙组件的错误时被调用。可以返回 false
以阻止该错误继续向上传播。
import { onErrorCaptured } from 'vue';
onErrorCaptured((err, instance, info) => {
console.log('onErrorCaptured: 捕获到错误', err, instance, info);
return false; // 阻止错误继续传播
});
渲染处理
onRenderTracked
在虚拟 DOM 进行跟踪时调用,主要用于调试。
import { onRenderTracked } from 'vue';
onRenderTracked((e) => {
console.log('onRenderTracked: 虚拟 DOM 进行跟踪', e);
});
onRenderTriggered
在虚拟 DOM 渲染触发时调用,主要用于调试。
import { onRenderTriggered } from 'vue';
onRenderTriggered((e) => {
console.log('onRenderTriggered: 虚拟 DOM 渲染触发', e);
});
完整的生命周期钩子函数使用
以下是一个包含所有生命周期钩子函数的 Vue 组件示例:
<template>
<div>
<h1>{{ message }}</h1>
</div>
</template>
<script>
import { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, onErrorCaptured, onRenderTracked, onRenderTriggered, onActivated, onDeactivated, onServerPrefetch } from 'vue';
export default {
setup() {
const message = ref('Hello Vue 3!');
onBeforeMount(() => {
console.log('onBeforeMount: 挂载开始之前被调用');
});
onMounted(() => {
console.log('onMounted: 组件挂载到 DOM 后被调用');
});
onBeforeUpdate(() => {
console.log('onBeforeUpdate: 数据更新时被调用');
});
onUpdated(() => {
console.log('onUpdated: 虚拟 DOM 重新渲染和打补丁之后被调用');
});
onBeforeUnmount(() => {
console.log('onBeforeUnmount: 实例销毁之前被调用');
});
onUnmounted(() => {
console.log('onUnmounted: 实例销毁之后被调用');
});
onErrorCaptured((err, instance, info) => {
console.log('onErrorCaptured: 捕获到错误', err, instance, info);
return false;
});
onRenderTracked((e) => {
console.log('onRenderTracked: 虚拟 DOM 进行跟踪', e);
});
onRenderTriggered((e) => {
console.log('onRenderTriggered: 虚拟 DOM 渲染触发', e);
});
onActivated(() => {
console.log('onActivated: 组件被激活');
});
onDeactivated(() => {
console.log('onDeactivated: 组件被停用');
});
onServerPrefetch(() => {
console.log('onServerPrefetch: 服务端预取数据');
});
return {
message
};
}
};
</script>
<style scoped>
h1 {
color: #42b983;
}
</style>
通过这个简单的例子,我们可以看到 Vue 组件从创建、更新到销毁的整个生命周期过程:
- 创建阶段:
onBeforeMount
和onMounted
分别在组件挂载到 DOM 前后被调用,进行初始化和初次渲染的操作。 - 更新阶段:
onBeforeUpdate
和onUpdated
在响应式数据更新前后被调用,进行更新前的准备和更新后的处理。 - 销毁阶段:
onBeforeUnmount
和onUnmounted
在组件实例销毁前后被调用,进行清理操作。
总结
通过本文的学习,我们深入理解了 Vue 3 组件的生命周期钩子函数及其在浏览器中的实际应用。我们通过具体代码示例,解析了组件从创建、挂载、更新到销毁的整个过程。
掌握这些生命周期钩子函数,不仅有助于我们在实际开发中更有效地管理组件,还能帮助我们更好地调试和维护代码。希望本文能够帮助你在 Vue 3 的使用过程中更加得心应手,为你的前端开发工作带来更多的灵感和帮助。写文章不易,可以给文章点个赞哦😊。
转载自:https://juejin.cn/post/7399587895369629711