直接回答:Vue 3 把模板编译成渲染函数时做静态分析,把“哪些节点永远不变、哪些绑定的什么会变”编码进产物:静态节点提升(hoist)出渲染函数只创建一次、Patch Flag 给动态节点打上变化类型位标记(TEXT=1、CLASS=2、PROPS=4…)、Block Tree 把含动态节点的子树打平成数组,更新时只遍历动态节点列表,跳过整棵静态子树——diff 从 O(全树) 降到 O(动态节点数)。

展开解析:逐项看收益:静态提升——模板里 100 个静态节点编译成一个 _hoisted_1 常量 vnode,重渲染直接复用引用,连 diff 都不进;Patch Flag——传统 diff 要全字段对比(class、style、props、children 逐一来),位标记让运行时直奔主题:flag 是 TEXT 就只比文本,是 PROPS 就只比编译期已知的动态 prop 名数组,未知名的动态绑定(v-bind="obj")退化为全对比;Block Tree——嵌套结构里动态节点被收集到 block 的 dynamicChildren 数组,父 block 更新时扁平遍历,静态中间层完全跳过。配套优化:v-once 标记纯静态块、事件缓存(cacheHandlers 避免每次渲染新建函数触发子组件无效更新)、SSR 场景静态节点直接序列化成字符串。与 React 的对比是方法论之争:React 把优化留给开发者(memo/useMemo/useCallback 手动声明依赖),Vue 用编译器自动分析——模板语法受限(对比 JSX 的自由 JS)换来了自动精确更新。边界:flag 分析失效于动态结构(v-for 内容复杂化),开发者的责任是写好 key 与拆分稳定子树。

追问方向:为什么 v-memo 很少需要?Svelte/Solid 的编译优化与 Vue 的路线差异?

(约 490 字)