微任务执行阶段做dom更新优化,核心是利用其“当前任务结束、浏览器渲染前集中执行”特性合并多次dom操作,避免重复重排重绘;通过queuemicrotask或promise.then收拢变更,支持状态合并;需避免微任务中读取布局信息;mutationobserver可构建可控更新管道;结合requestanimationframe对齐渲染帧更稳妥;框架如vue/react已天然对齐微任务机制。

微任务执行阶段做 DOM 更新优化,核心是利用它“在当前任务结束、浏览器渲染前集中执行”的特性,把多次零散的 DOM 操作合并成一次有效更新,避免中间状态触发重复重排重绘。
把多次变更攒到一个微任务里统一处理
同步代码中连续修改 DOM,浏览器可能逐次尝试布局计算;而用 Promise.resolve().then 或 queueMicrotask 包裹,能确保这些操作被收拢到同一批微任务中执行:
- 同一轮事件循环内多次调用
queueMicrotask(() => {...}),最终只触发一次批量执行 - 内部逻辑可做状态合并,比如只保留最后一次输入值、去重节点插入、跳过中间过渡态
- 避免在微任务里读取
offsetHeight、getBoundingClientRect()等布局信息,否则会强制同步回流,破坏优化效果
用 MutationObserver 做变更缓冲与响应式调度
MutationObserver 回调本身在微任务中执行,适合构建可控的 DOM 更新管道:
- 创建一个不挂载的“缓冲容器”,所有待更新操作先写入该容器(如 appendChild 到 fragment)
- 用 MutationObserver 监听该容器变化,一旦有子节点增删,就在回调中批量提取、加工、再一次性挂载到真实 DOM
- 比 setTimeout 更及时,比同步操作更稳定,也更容易和数据响应式系统对齐
搭配 requestAnimationFrame 对齐渲染帧
纯微任务虽快,但若在渲染帧末尾执行,仍可能挤占下一帧时间。更稳妥的做法是分两步:
- 先用微任务收集、归并、去抖所有待更新数据(例如表单输入节流、滚动位置缓存)
- 再在 下一个 requestAnimationFrame 回调中执行实际 DOM 写入
- 这样既避开同步布局抖动,又确保 DOM 变更落在浏览器渲染周期内,帧率更稳
注意 Vue/React 场景下的自然对齐
框架自身的更新队列(如 Vue 的 queueJob、React 的 setState 批量机制)默认就基于微任务。手动使用微任务更新 DOM,能自动与它们节奏一致:
- 在事件处理器中用
Promise.then更新 UI,不会打断框架的 diff 流程 - 避免混合使用
setTimeout和微任务,否则容易造成 DOM 状态错位(比如 $nextTick 回调执行时,DOM 还没被框架更新完) - 需要读取最新 DOM 时,优先用框架提供的机制(如
this.$nextTick或await nextTick()),而非自行轮询或加延时










