Skip to content

18.什么是重绘和回流?

  • 重排(回流)Reflow: 添加元素、删除元素、修改大小、移动元素位置、获取位置相关信息
  • 重绘 Repaint:页面中元素样式的改变并不影响它在文档流中的位置。

我们应当尽可能减少重绘和回流。

1.强制同步布局问题

JavaScript 强制将计算样式和布局操作提前到当前的任务中

html
<div id="app"></div>
<script>
    function reflow() {
        let el = document.getElementById('app');
        let node = document.createElement('h1');
        node.innerHTML = 'hello';
        el.appendChild(node);
        // 强制同步布局
        console.log(app.offsetHeight);
    }
    requestAnimationFrame(reflow)
</script
<div id="app"></div>
<script>
    function reflow() {
        let el = document.getElementById('app');
        let node = document.createElement('h1');
        node.innerHTML = 'hello';
        el.appendChild(node);
        // 强制同步布局
        console.log(app.offsetHeight);
    }
    requestAnimationFrame(reflow)
</script

2.布局抖动(layout thrashing)问题

在一段 js 代码中,反复执行布局操作,就是布局抖动

js
function reflow() {
  let el = document.getElementById("app");
  let node = document.createElement("h1");
  node.innerHTML = "hello";
  el.appendChild(node);
  // 强制同步布局
  console.log(app.offsetHeight);
}
window.addEventListener("load", function () {
  for (let i = 0; i < 100; i++) {
    reflow();
  }
});
function reflow() {
  let el = document.getElementById("app");
  let node = document.createElement("h1");
  node.innerHTML = "hello";
  el.appendChild(node);
  // 强制同步布局
  console.log(app.offsetHeight);
}
window.addEventListener("load", function () {
  for (let i = 0; i < 100; i++) {
    reflow();
  }
});

3.减少回流和重绘#

  • 脱离文档流
  • 渲染时给图片增加固定宽高
  • 尽量使用 css3 动画
    html
    <style>
      /* ctrl+shift+p (show Rending 查看重绘操作) */
      @keyframes rotate {
        from {
          transform: rotate(0deg);
          /* width: 100px; */
        }
        to {
          transform: rotate(360deg);
          /* width: 500px; */
        }
      }
      #app {
        width: 100px;
        height: 100px;
        background: red;
        animation: rotate 0.2s linear infinite;
      }
    </style>
    <div id="app"></div>
    <style>
      /* ctrl+shift+p (show Rending 查看重绘操作) */
      @keyframes rotate {
        from {
          transform: rotate(0deg);
          /* width: 100px; */
        }
        to {
          transform: rotate(360deg);
          /* width: 500px; */
        }
      }
      #app {
        width: 100px;
        height: 100px;
        background: red;
        animation: rotate 0.2s linear infinite;
      }
    </style>
    <div id="app"></div>
  • 可以使用 will-change 提取到单独的图层中
    html
    <div style="will-change: transform">我是单独的图层</div>
    <div style="will-change: transform">我是单独的图层</div>

Released under the MIT License.