文本节点处理是diff算法中最直接的优化环节:当新旧节点均为纯文本时,严格相等(===)比对后决定是否更新textcontent;混排时单向替换避免反复切换;ssr hydration阶段字节级比对可跳过赋值。

文本节点的处理是 Diff 算法中最直接也最常被优化的一环——它不涉及子节点递归、无需双指针移动,但必须快速判定是否需要更新内容,避免无谓的 DOM 文本赋值。
文本节点的快速判等逻辑
当新旧虚拟节点中任一为纯文本节点(即 newVnode.text !== undefined 且 oldVnode.text !== undefined),算法会跳过所有子节点比对流程,直接进入文本更新分支:
- 若 newVnode.text === oldVnode.text,不做任何操作,复用原有真实 DOM 的 textContent;
- 若不相等,则仅执行 el.textContent = newVnode.text,一次赋值完成更新;
- 该判断在
patchVnode函数开头优先执行,属于“短路退出”式优化,避免后续冗余逻辑。
文本与非文本混排时的处理边界
真实场景中,文本常与元素节点共存于同一父级 children 数组。Diff 需明确区分两类情况:
-
oldVnode 是文本,newVnode 是数组(含子节点):先清空老节点的文本内容(
el.textContent = ''),再遍历创建新子节点并插入; -
oldVnode 是数组,newVnode 是文本:先卸载全部旧子节点(逐个调用
removeNode),再设置el.textContent; - 这种单向替换设计避免了“文本→元素→文本”的反复切换开销,也符合 DOM 渲染的不可逆语义。
避免隐式类型转换导致误更新
Vue 的实现中会对文本值做严格相等(===)比对,而非宽松相等(==)或字符串化后比对:
- 例如
newVnode.text = 123与oldVnode.text = '123'被视为不同,会触发更新; - 这保证了响应式更新的准确性——数值 123 和字符串 '123' 在 Vue 数据流中语义不同;
- 开发者无需手动
String(val),框架已在 patch 前完成标准化(h 函数中 text 字段始终为 string 或 undefined)。
服务端渲染(SSR)下的特殊跳过
在 hydration 阶段(客户端激活服务端 HTML),若发现真实 DOM 中的文本内容与 newVnode.text 完全一致,且节点已存在 elm 引用,会跳过 textContent 赋值:
- 利用服务端输出的确定性,省去一次 DOM 属性写入;
- 该优化依赖
isSameNode+node.nodeType === 3+ 字符串字节级比对; - 对首屏性能敏感场景(如新闻列表页)有可测的微秒级收益。











