在requestAnimationFrame回调中操作DOM会出现什么情况?
DOM操作与reflow的认知纠正
- 不是每一次插入DOM这类操作都会立刻触发reflow,浏览器默认会对DOM修改做批量合并,只有当你修改DOM后立刻读取布局相关属性(比如
offsetWidth、getBoundingClientRect()等)时,才会强制浏览器同步执行reflow返回准确值,否则所有DOM修改都会攒到渲染阶段统一计算。
window.requestAnimationFrame()方法会告知浏览器你希望执行动画,并请求浏览器在下一次重绘前调用指定的函数来更新动画。
rAF相关疑问解答
你担心的「rAF回调里改DOM+递归入队rAF会导致无限循环、无法渲染」的情况完全不会发生,浏览器的单帧渲染流水线有严格的固定执行顺序,不会被中途打断:
- 首先执行当前帧的所有同步任务、微任务
- 按顺序执行所有当前帧已入队的rAF回调
- 基于rAF回调执行完后的最终DOM状态,统一执行样式计算、布局(reflow)、绘制(repaint)、图层合成,把最终内容输出到屏幕上
- 你在本次rAF回调里新入队的rAF请求,会被放到下一帧的rAF队列中,等待下一帧重绘前才会执行,完全不会干预本次的渲染流程
我们日常用rAF实现动画都是基于这个逻辑,比如最常见的位移动画:
const ele = document.querySelector('.animate-element') let leftOffset = 0 function updatePosition() { // rAF回调内修改DOM样式 ele.style.left = leftOffset + 'px' leftOffset += 1 // 回调末尾入队下一次rAF请求 requestAnimationFrame(updatePosition) } // 启动动画 requestAnimationFrame(updatePosition)
这段代码每一次修改的元素位置都会在当前帧正常渲染到屏幕上,完全不会出现卡死无渲染的问题。
内容的提问来源于stack exchange,提问作者BHARGEY MEHTA
相关产品推荐
相关产品推荐

