Skip to content

🧠 1. Vue3 Virtual DOM 的设计目标

Vue3 的 Virtual DOM 不是 React 那种纯 VDOM,而是:

“带编译优化的 Virtual DOM” template → Compiler → 最小化的 VDOM 对象 + 静态标记(patchFlags) → Runtime diff 更快

Vue3 的设计核心是: 减少 VDOM 计算量,减少对比次数,尽可能生成编译期可确定的内容。

所以它比 React 更快,特别是大量静态模板的情况下。

🧩 2. Vue3 渲染流程(runtime)

Vue3 主要由两部分组成:

  • reactivity 响应式系统 —— 负责依赖追踪
  • runtime-core 渲染系统 —— 负责 VDOM → DOM

渲染大致流程如下:

template  →  compiler-dom (生成 render 函数)

            render() 生成 vnode 树

            patch(vnode, container)

            操作真实 DOM

Vue3 的 render 函数内部使用:

  • h() / createVNode():创建虚拟节点
  • patch():对比新旧 vnode
  • effect():组件渲染响应式收集器

🔧 3. VNode(虚拟节点)是什么?

JS 对象,用来描述 DOM:

js
const vnode = {
  type: 'div',
  props: { id: 'app' },
  children: 'Hello'
}

Vue3 内部使用 createVNode() 来创建:

ts
export function createVNode(type, props, children) {
  return {
    type,
    props,
    children,
    shapeFlag: xxx,     // 节点类型(元素、组件、文本…)
    patchFlag: xxx,     // 静态标记(更快 diff)
  }
}

重点字段:

  • shapeFlag:快速判断节点类型(不需要频繁 typeof)
  • patchFlag:编译期注入的优化标记(避免全量 diff)

🎯 4. 响应式系统如何触发重新渲染?

Vue3 的响应式核心是:

  • effect(fn):收集依赖(组件渲染函数)
  • track():记录依赖
  • trigger():触发更新(调度渲染)

在组件挂载时,会执行:

js
effect(() => {
  component.update()
})

当响应数据变更时:

js
trigger(obj.key)
  → scheduler
     → 重新执行组件的 update() → patch()

🔵 这里的关键:渲染函数本身是一个 effect,因此数据变化 = 重新生成 vnode 树 → diff

🧮 5. Diff 过程(核心 patch)

Vue3 patch 的核心逻辑:

ts
patch(n1, n2, container) {
  if (!n1) {
    mount(n2)
  } else if (n1.type !== n2.type) {
    replace(n1, n2)
  } else {
    patchElement()
  }
}

差异类型:

  • props 改变 → patchProps
  • children 改变 → patchChildren
  • 文本 → patchText

🔥 6. Vue3 最重要的优化:patchFlags(编译器生成)

Vue3 与 React 最大区别之一:编译器对 diff 的提前优化

例如:

vue
<div :id="dynamic" class="static">Hello</div>

编译后 render:

js
return (openBlock(), createElementBlock(
  "div",
  {
    id: dynamic
  },
  "Hello",
  8 /* PROPS */,
  ["id"]
))

其中:

  • patchFlag = 8 (PROPS) → 表示仅 props 变化、并且只有 "id" 动态

Vue runtime 就能做到:

只 patch "id",不 diff 其他属性 不 diff class(静态) 不 diff children(静态)

📌 Vue3 静态提升与 patchFlag 优化使它的渲染性能远超 React 的纯 VDOM diff。

🧱 7. 静态提升(hoist static)

如果有静态节点:

vue
<div><span>static</span></div>

它会被提升到渲染函数外:

js
const _hoisted_1 = /*#__PURE__*/ createVNode("span", null, "static");

return () => (
  createVNode("div", null, [_hoisted_1])
)

静态节点不参与 diff! 这是 Vue 3 最大的性能优势。

🍃 8. Fragment / Teleport / Suspense 的渲染机制

Fragment

一个组件可以返回多个根节点,内部 patch 时特殊处理多个 children。

Teleport

渲染时不在父组件中操作,而是把 DOM 直接移动到指定容器。

Suspense

处理异步组件渲染,fallback → resolve → patch。

🚀 9. Vue3 渲染流程总览图(非常关键)

       template

     compiler-dom
 (静态提升 + patchFlags)

      render()

      createVNode()

        effect()
(初次渲染收集依赖)

        patch()
      /    |    \
 mount  diff  update props

     update DOM

数据变化 → trigger → effect → patch → DOM 更新

你看完这个就已经对 Vue3 渲染机制有框架级理解了。