我什么时候需要调用requestAnimationFrame()?

时间:2018-03-09 16:14:11

标签: javascript css performance requestanimationframe

我确实理解requestAnimationFrame()在运行不断更改样式属性的动画时非常有用。

const e = document.getElementById('e');
let count = 0;

function move(timestamp) {
  e.style.left = ++count + 'px';
  requestAnimationFrame(move);
};

requestAnimationFrame(move);

现在我的问题是:requestAnimationFrame中包装改变视图外观的所有内容是否有意义?

换句话说,这个伪代码示例会比没有requestAnimationFrame的情况有更好的表现吗?

const e = document.getElementById('e');
let f = document.createDocumentFragment();

nodes.forEach((node, index) => {
    f.appendChild(node);
}

requestAnimationFrame(timestamp => {
    e.classList.toggle('active');
    container.classList.add('active');
    container.appendChild(fragment);
});

1 个答案:

答案 0 :(得分:-1)

简短的回答是“使用rAF进行频繁更新”。在进行任何类型的DOM突变时,更重要的是将尽可能多的DOM批量转换为单个“事件循环”,以便允许浏览器尽可能少地重排/重绘。对于大多数一次性DOM突变,不需要使用rAF。但是,您可能不知道是否已经存在动画,在这种情况下,使用rAF允许浏览器确定执行DOM更新的最佳时间。以下是一些不良代码的示例(仅供参考):

let count = 10;
while(count--) setTimeout(() => {
  const div = document.createElement('div');
  document.body.appendChild(div)
});

每个超时都发生在一个单独的事件循环中,每个超时都在修改DOM。这可能会导致浏览器多次重排/重绘。要彻底改进这一点,您可以批量处理DOM更新,如下所示:

let c = 10;
const divs = [];
const doAppend = () => { 
  while(divs.length) document.body.appendChild(divs.shift()) 
};
while(c--) setTimeout(() => {
  divs.push(document.createElement('div'));
  if (++c === 9) doAppend();
});

如果你经常这样做,那就用rAF:

const doAppend = () => requestAnimationFrame(() => { 
  while(divs.length) document.body.appendChild(divs.shift()) 
});