页面渲染是事件循环中动态插入的可选步骤,发生在宏任务结束、微任务清空后,由浏览器根据帧率、DOM变更和可见性决定是否执行;未达渲染条件时修改DOM不会立即生效。

页面渲染在事件循环中不是固定阶段,而是浏览器根据帧率、任务负载和可见性动态插入的“可选步骤”,通常发生在一个宏任务执行完毕、微任务队列清空之后,下一个宏任务开始之前。
渲染不是每次循环都发生
浏览器目标是 60fps(约每 16.7ms 一帧),但不会机械地“每轮事件循环都强制渲染”。是否渲染取决于:
- DOM 或样式是否实际发生了需要更新的变更(比如改了
transform或opacity) - 当前帧是否还有足够时间完成 Layout → Paint → Composite 全流程(若已超时,该帧跳过渲染)
- 页面是否处于后台标签页(此时渲染可能被降频甚至暂停)
标准事件循环中的典型顺序
一次较完整的循环大致如下(简化版):
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
- 执行一个宏任务(如
setTimeout回调、用户点击事件处理函数) - 立即清空全部微任务(
Promise.then、MutationObserver等) - 浏览器判断:是否需要渲染? 若满足条件(有视觉变化 + 时间充裕),则触发渲染管线(Style → Layout → Paint → Composite)
- 从任务队列中取出下一个宏任务,重复上述过程
为什么你改了 DOM 看不到立即生效?
因为 DOM 修改只是“标记脏节点”,真正计算布局和绘制要等到渲染时机到来。常见误区:
- 读取
offsetHeight或getComputedStyle会强制同步触发布局(reflow),打断流水线,拖慢性能 - 连续多次 DOM 写操作未批量处理,会导致多次不必要的渲染准备
- 把大量逻辑塞进单个宏任务(如长 for 循环),导致渲染被延后甚至丢帧
如何主动触发或等待渲染完成?
用标准 API 明确对接渲染时机:
-
requestAnimationFrame(callback):回调会在**下一帧渲染前**执行,适合动画更新 -
await new Promise(r => requestAnimationFrame(r)):等一帧结束 -
queueMicrotask():比Promise.then更轻量,用于微任务级调度

















