大家好,我是 前端架构师 - 大卫。
更多优质内容请关注微信公众号 @前端大卫。
初心为助前端人🚀,进阶路上共星辰✨,
您的点赞👍与关注❤️,是我笔耕不辍的灯💡。
前言
Vue 3 在性能优化方面做出了许多改进,主要集中在以下两个核心点:
- 🚀 更快的虚拟 DOM:优化了 Diff 算法,引入 Block 静态提升,提高渲染性能。
- 📦 更小的体积:使用 Tree Shaking 机制,按需引入功能,减少打包体积。
相比 Vue 2,Vue 3 通过这些优化让应用运行更流畅,占用资源更少。接下来,我们用通俗的方式详细解析这些优化的原理和效果。
一、更快的虚拟 DOM
在 Vue 3 中,基于 Block 的静态提升 和 编译优化 主要是指 在模板编译阶段 对静态内容和动态内容进行优化,减少不必要的虚拟 DOM 重新渲染,提高性能。我们来详细拆解这两个优化策略:
1️⃣ 基于 Block 的静态提升
🟢 概念
Block 是什么? Block = Vue 3 生成的一个"静态区域" 。 静态内容 (不变的部分)被分到 Block 里,不会重新对比。 动态内容(会变化的部分)才会重新对比,减少计算量。
在 Vue 2 中,每次组件渲染都会重新创建整个 虚拟 DOM 树 ,即使某些部分是静态的(不会变化)。Vue 3 通过 静态提升 ,将不变的节点(静态节点)提升到 渲染函数外部,这样就不会在每次更新时重新创建这些静态节点,从而减少不必要的计算。
🟢 示例
html
<template>
<h1>Vue 3 编译优化</h1>
<p>{{ count }}</p>
</template>
Vue 2 渲染逻辑
js
// 每次 render() 触发时,都会重新创建整个 VNode 树
function render() {
return h("div", [
h("h1", "Vue 3 编译优化"),
h("p", this.count) // 动态节点
]);
}
Vue 3 渲染逻辑
js
// Vue 3 会把静态节点 (h1) 提升到 render 之外,只在初始化时创建一次
const _hoisted_1 = h("h1", "Vue 3 编译优化");
function render() {
return h("div", [
_hoisted_1, // 直接复用静态节点
h("p", this.count) // 仅动态部分需要更新
]);
}
✅ 优化点
h1
是静态的,Vue 3 只创建一次,并存入_hoisted_1
变量。- 渲染时 不会重复创建
h1
,提高了性能。
2️⃣ 基于 Block 的编译优化
🟢 概念
在 Vue 2 中,每次组件更新时,整个模板都会重新进行 虚拟 DOM 对比(diff) ,即使某些部分没有变化。Vue 3 引入 Block Tree ,可以 跟踪动态节点,只更新变化的部分,而不是整棵 VNode 树。
🟢 示例
vue
<template>
<div>
<h1>Vue 3</h1>
<button @click="count++">点击次数:{{ count }}</button>
</div>
</template>
Vue 2 渲染逻辑
在 Vue 2 中,render
生成的 VNode 结构如下:
js
function render() {
return h("div", [
h("h1", "Vue 3"), // 静态,但仍然会被重新 diff
h("button", { onClick: this.count++ }, `点击次数:${this.count}`)
]);
}
- 每次
count
变化,Vue 2 都会重新 diff 整个div
及其子节点。 - 即使
h1
没有变化,仍然会被 Vue 2 重新比对。
Vue 3 渲染逻辑
Vue 3 会在 编译阶段 生成一个 Block Tree(区块树),并将动态节点标记:
js
function render() {
return openBlock(), createElementBlock("div", [
_hoisted_1, // 这个 h1 是静态的,不会 diff
createVNode("button", { onClick: this.count++ }, `点击次数:${this.count}`)
]);
}
openBlock()
会创建一个 Block 并跟踪动态节点。createElementBlock()
只更新 Block 内部的 动态节点 ,即button
,h1
不会重复 diff。
✅ 优化点
- Vue 3 生成 Block Tree ,只追踪动态节点(如
button
),减少不必要的虚拟 DOM diff。 - 只更新动态内容,静态部分完全跳过,减少性能开销。
🎯 总结
优化策略 | 作用 | 影响的节点类型 | Vue 2 vs Vue 3 |
---|---|---|---|
静态提升(Static Hoisting) | 提前创建静态节点,避免重复渲染 | 纯静态节点(不会变化) | Vue 2 每次都重新创建,Vue 3 只创建一次 |
区块优化(Block Tree Optimization) | 追踪动态节点,跳过静态部分的 diff | 动态节点(会变化) | Vue 2 diff 整个模板,Vue 3 只 diff 变化的部分 |
二、更小的体积
Vue 3
使用 Tree Shaking
机制,未使用的 API 不会被打包进最终构建结果,使得体积更小。
1. Vue 2 是基于 全局 API 设计的
Vue
是一个单一的对象,包含所有 API(Vue.set
、Vue.delete
、Vue.observable
等)。
js
import Vue from "vue"; // Vue 整个包都会被引入
const app = new Vue({
data() {
return { count: 0 };
}
});
2. Vue 3 采用了 按需引入(按模块导入)的方式
js
import { createApp, ref } from "vue"; // 只导入用到的 API
const app = createApp({
setup() {
const count = ref(0);
return { count };
}
});
Tree Shaking 只适用于 ES Module(ESM),如果使用 require(),打包工具无法静态分析。
总结
Vue 3 通过这些优化,使应用 运行更快、占用更少资源 ,尤其在 大规模组件更新 时,性能提升更加明显! 🚀