最小化真实渲染靠“只操作真正变了的部分”,核心是render→diff→patch闭环:用js对象树描述ui绕过dom操作,同级diff、key优化列表、批量patch提交,避免内联函数和可变数据。

最小化真实渲染不是靠“少操作”,而是靠“只操作真正变了的那部分”。虚拟DOM本身不加快单次渲染,它把昂贵的真实DOM操作压缩到最低限度——核心在于 render → diff → patch 这三步闭环。
用JS对象树代替直接DOM操作
真实DOM节点操作(如 document.createElement、el.appendChild)会立刻触发浏览器布局计算和样式重排。虚拟DOM第一步就是绕过它:用普通JS对象描述结构,比如:
{ tag: 'div', props: { id: 'list' }, children: [ { tag: 'li', props: {}, children: ['Item 1'] } ] }- 这个对象不接触浏览器,纯内存运算,创建和修改成本极低
- 所有UI变化都先反映在这棵树上,而不是直接动真实DOM
只比对同级、跳过跨层,让diff快且准
diff算法不逐像素比,而是按规则快速收敛差异范围:
- 只在同一层级做节点对比,不跨层追踪移动(比如不会把子节点A从父节点X挪到父节点Y去匹配)
- 节点类型不同(
div→span)直接整块替换,不浪费时间比属性 - 文本节点变化时,只更新textContent,不重建元素
- 列表渲染必须带
key,否则diff无法区分“移动”和“新增+删除”,容易全量重绘
批量生成补丁,一次提交到真实DOM
diff完不是马上改DOM,而是攒出一个最小操作集(patch),再统一执行:
- 例如:仅需
setTextContent更新一个文本,或setAttribute改一个class,而不是重新插入整个 - 多个变更合并为一次DOM操作,避免多次触发重排(reflow)和重绘(repaint)
- 真实DOM更新被延迟到浏览器空闲帧(如 requestIdleCallback)或下一帧(requestAnimationFrame),进一步降低感知卡顿
避免无意义的虚拟树重建
即使用了虚拟DOM,写法不当也会白忙一场:
- 不要在render函数里写
onClick={() => doSomething()}这类内联函数——每次渲染都生成新函数,导致props引用变化,触发不必要的diff - 列表数据用不可变方式更新(如
[...items, newItem]),而非push()原地修改,确保diff能正确识别增删 - 复杂组件可用
React.memo或shouldComponentUpdate拦截未变化的子树,跳过其虚拟树生成和diff
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











