Skip to content

浏览器原理

  • 异步布局优化
    • 刷新也是批处理的,会打标记,然后在下一帧进行统一刷新。
  • 强制同步布局
    • 打破上述流程,在”写“完之后,紧接着”读“。
      • 什么是“读”操作? 就是那些需要获取元素精确几何属性的 API:
        • element.offsetWidth, element.offsetHeight
        • element.clientWidth, element.clientHeight
        • element.scrollWidth, element.scrollHeight
        • element.scrollTop, element.scrollLeft
        • element.getBoundingClientRect()
        • getComputedStyle()
  • 性能杀手:“布局抖动(Layout Thrashing)”
    • “写 -> 读 -> 写 -> 读...” 的交替操作
js
const myElement = document.getElementById('box');

// 1. 写入操作,使布局“失效”,变更被放入队列
myElement.style.width = '200px'; 

// 2. 读取操作,为了获取准确的 offsetWidth 值...
// ...浏览器不得不强制清空队列,并立即执行布局计算
console.log(myElement.offsetWidth);

错误的示范,频繁读写:

js
function resizeAll() {
    const divs = document.querySelectorAll('.box');
    const firstBox = divs[0];
    
    // 读取第一个盒子的宽度
    const width = firstBox.offsetWidth;

    for (let i = 1; i < divs.length; i++) {
        // 这是一个灾难性的循环
        // 写操作
        divs[i].style.width = width + 'px';
        // 马上又进行了一个不必要的读操作,只是为了举例
        console.log(divs[i].offsetWidth); // 这一行会强制触发一次同步布局
    }
}

优化:

js
function resizeAllOptimized() {
    const divs = document.querySelectorAll('.box');
    const firstBox = divs[0];

    // --- 批量读取阶段 ---
    const width = firstBox.offsetWidth; // 读一次
    
    // --- 批量写入阶段 ---
    for (let i = 1; i < divs.length; i++) {
        // 只有写操作,浏览器可以缓存它们
        divs[i].style.width = width + 'px'; 
    }

    // 在这个函数执行完毕后,浏览器才会进行一次总的布局计算。
    // 从 N 次布局优化为了 1 次。
}
本站访客数 人次 本站总访问量