vue3中静态提升和patchflag实现
作者:互联网
2026-04-14
1. 更快的 Virtual DOM (VDOM) - 具体体现
Vue 3 在虚拟 DOM 方面的改进是多方面的,旨在提高渲染效率和减少不必要的计算。
A. 编译时优化 (Compile-time Optimizations)
这是 Vue 3 与 Vue 2 最大的区别之一。Vue 2 的 VDOM diff 过程是在运行时进行的,它需要逐个比较节点和属性。而 Vue 3 的编译器在构建阶段就能分析模板,生成包含“优化提示”的渲染函数。
- 静态提升 (Hoisting/Diff Skipping): 编译器会识别出模板中的静态节点(即内容不会改变的节点),并将它们提取到渲染函数之外。在后续更新时,Vue 完全跳过对这些节点的比较,因为它们永远不会变。
<div>
<h1>This is statich1>
<p>{{ dynamicValue }}p>
<span>Another static contentspan>
div>
在 Vue 2 中,每次更新 编译器会知道这个 虽然核心思想仍是双端 Diff,但 Vue 3 的实现更加优化,尤其是在处理列表更新时。 总结 VDOM 性能提升体现: {{ greeting }} 关键点解读: 通过这种方式,Vue 3 在编译时就对模板进行了深度优化,使得运行时的渲染和更新过程更加高效 相关推荐dynamicValue 时,都会对整个 和 会被提升,只对 进行比较,大大减少了工作量。
<p :class="className">{{ message }}p>
元素可能变化的部分是 class 和文本内容,并打上相应的 flag。更新时就不会去检查它的 id 或其他不变的属性。B. 更高效的 Diff 算法
2.静态提升和pathflag例子
<template>
<div id="app">
<h1 class="title">Welcome to My Apph1>
<p>{{ greeting }}p>
<ul>
<li>Static Item 1li>
<li>Static Item 2li>
<li>{{ dynamicItem }}li>
ul>
<button @click="changeGreeting">Change Greetingbutton>
div>
template>
<script setup>
import { ref } from 'vue';
const greeting = ref('Hello Vue 3!');
const dynamicItem = ref('Dynamic Item 3');
const changeGreeting = () => {
greeting.value = 'Greetings from Vue 3!';
};
script>
编译器分析和优化过程:
:标签名、内容、Welcome to My App
class 属性都不变,是静态节点。 和 :标签名和内容都不变,是静态节点。:标签名、内容和事件处理器(@click)都不变,是静态节点。
:内容 {{ greeting }} 是动态的。:内容 {{ dynamicItem }} 是动态的。id 是静态的,但它包含了动态子节点,因此自身是动态的。
_hoisted_1, _hoisted_2 等)。这样它们只会被创建一次。
节点:它的内容是动态的,编译器会为其 VNode 添加 patchFlag: Text (数值通常是 1)。这告诉运行时,只需要比较和更新它的文本内容。 节点:它的内容是动态的,同样会添加 patchFlag: Text (数值通常是 1)。 节点:它的子节点列表是动态的(因为包含动态的 ),编译器会为其添加 patchFlag: Children (数值通常是 8 或更复杂的组合)。这告诉运行时,需要对其子节点进行 diff。编译后生成的渲染函数(简化示意):
import { createElementVNode as _createElementVNode, createTextVNode as _createTextVNode, Fragment as _Fragment, openBlock as _openBlock, createBlock as _createBlock, toDisplayString as _toDisplayString } from 'vue'
// --- 静态提升的 VNodes ---
// 这些 VNodes 只在模块加载时创建一次,后续渲染直接复用
const _hoisted_1 = /*#__PURE__*/_createElementVNode("h1", { class: "title" }, "Welcome to My App", -1 /* HOISTED */)
const _hoisted_2 = /*#__PURE__*/_createTextVNode("Static Item 1")
const _hoisted_3 = /*#__PURE__*/_createTextVNode("Static Item 2")
const _hoisted_4 = /*#__PURE__*/_createElementVNode("button", { onClick: "changeGreeting" }, "Change Greeting", -1 /* HOISTED */)
// -----------------------------------
function render(_ctx, _cache, $props, $setup, $data, $options) {
// `_ctx` 通常包含 `greeting` 和 `dynamicItem` 等响应式数据
return (_openBlock(), _createBlock("div", { id: "app" },
[
_hoisted_1, // 直接复用,无需 diff
_createElementVNode("p", null, _toDisplayString($setup.greeting), 1 /* TEXT */), // patchFlag: 1
_createElementVNode("ul", null, [
_hoisted_2, // 直接复用,无需 diff
_hoisted_3, // 直接复用,无需 diff
_createElementVNode("li", null, _toDisplayString($setup.dynamicItem), 1 /* TEXT */) // patchFlag: 1
], 16 /* FULL_PROPS */), // patchFlag: 16 (这里可能表示子节点是动态的,需要 diff)
_hoisted_4 // 直接复用,无需 diff
]
))
}
_hoisted_1, _hoisted_2, _hoisted_3, _hoisted_4:这些都是在编译时创建好的静态 VNode 对象。/* HOISTED */ 注释表明它们被提升了。在运行时,渲染函数直接使用这些对象,而不必每次都重新创建。_createElementVNode("p", ...) 和 _createElementVNode("li", ...):这些是动态节点,每次渲染时都需要重新创建 VNode。1 /* TEXT */:这就是 patchFlag。它告诉运行时,这个 VNode 只需要关心文本内容的变化。当 $setup.greeting 或 $setup.dynamicItem 改变时,运行时只需比较新旧文本字符串,然后更新真实 DOM 的 textContent,而不需要比较 class、id 等其他属性。16 /* FULL_PROPS */ (或类似的数值): 的 patchFlag 表明其子节点是动态的,需要进行子节点的 diff。
专题
+ 收藏
+ 收藏
+ 收藏
+ 收藏
+ 收藏
+ 收藏
最新数据
相关文章
目录:VTJ.PRO 在线应用开发平台技术揭秘
4.响应式系统基础:从发布订阅模式的角度理解 Vue3 的数据响应式原理
vue3中静态提升和patchflag实现
你的 Vue 3 ref(),VuReact 会编译成什么样的 React?
你的 Vue 3 reactive(),VuReact 会编译成什么样的 React?
Vue3 转 React:组件透传 Attributes 与 useAttrs 使用详解|VuReact 实战
使用 VueUse 构建一个支持暂停/重置的 CountUp 组件
vue2中使用 AntV G6
前端视频媒体带声音自动播放方案最佳实践和教程
[前端]可折叠容器组件、信息展示卡片组件
AI精选
