怎么理解回流和重绘?什么场景下会触发?

2024-07-19 22:25:35 158
在Web浏览器中,回流和重绘是渲染引擎用来展示页面内容的两个重要过程。这两个过程直接影响页面性能,因此理解它们的工作原理和触发场景对优化Web性能至关重要。

回流(Reflow)

回流,也叫布局(Layout),指的是浏览器重新计算页面元素的位置和几何属性的过程。当页面的结构、内容或大小发生变化时,浏览器需要重新计算元素的位置和尺寸,以确保页面的正确显示。回流是一个高耗时的操作,因为它会影响整个页面或页面的大部分内容。

触发回流的场景

  1. 添加或删除DOM元素:例如插入新元素或删除现有元素。
  2. 改变元素的几何属性:例如widthheightpaddingmarginborder等。
  3. 移动元素:例如改变元素的位置(position属性)。
  4. 改变字体:例如字体大小或字体家族变化。
  5. 窗口大小变化:例如调整浏览器窗口的大小。
  6. 计算样式:例如调用getComputedStyleoffsetHeight等会强制浏览器计算样式的属性或方法。

重绘(Repaint)

重绘指的是当元素的外观改变但不影响布局时,浏览器重新绘制这些元素。重绘不涉及重新计算元素的位置和尺寸,因此相对来说开销较小。

触发重绘的场景

  1. 改变元素的颜色:例如colorbackground-color等。
  2. 改变元素的透明度:例如opacity
  3. 改变元素的轮廓:例如outline属性。

回流和重绘的区别

  • 回流:会影响整个页面或页面的大部分,涉及布局计算,开销大。
  • 重绘:只影响元素的外观,不涉及布局计算,开销小。

优化回流和重绘

由于回流和重绘会影响页面性能,以下是一些减少回流和重绘的方法:

  1. 合并多次操作:例如一次性改变样式,而不是逐一改变。

    // 不推荐
    element.style.width = '100px';
    element.style.height = '100px';
    
    // 推荐
    element.style.cssText = 'width: 100px; height: 100px;';
    
  2. 使用类:通过添加或移除类来改变样式,而不是直接修改样式属性。

    .hidden {
        display: none;
    }
    
    element.classList.add('hidden');
    
  3. 脱离文档流:在操作DOM之前,先将元素脱离文档流,操作完成后再插入。

    const fragment = document.createDocumentFragment();
    for (let i = 0; i < 100; i++) {
        const div = document.createElement('div');
        fragment.appendChild(div);
    }
    document.body.appendChild(fragment);
    
  4. 避免逐项查询DOM属性:例如不要在循环中查询DOM属性,先缓存值再使用。

    const width = element.offsetWidth;
    for (let i = 0; i < 100; i++) {
        // 使用缓存的width,而不是每次都查询element.offsetWidth
        console.log(width);
    }
    
  5. 使用CSS3硬件加速:例如使用transformopacity,这些属性通常不会触发回流。

    .move {
        transform: translateX(50px);
        opacity: 0.5;
    }
    

总结

  • 回流(Reflow):涉及元素布局变化,开销大,触发场景包括添加或删除DOM元素、改变几何属性等。
  • 重绘(Repaint):涉及元素外观变化,开销小,触发场景包括颜色、透明度等变化。
  • 优化建议:合并操作、使用类、脱离文档流、缓存DOM查询结果、使用CSS3硬件加速等。