浏览器🧑‍💻 浏览器的渲染流程

DOM 的回流(Reflow)

  1. 元素的 大小 或者 位置 发生了变化(当页面布局和几何信息发生变化的时候),触发了重新布局,导致渲染树重新计算布局和渲染,如:

    1. 添加或删除可见的 DOM 元素;
    2. 元素的位置发生变化;
    3. 元素的尺寸发生变化;
    4. 内容发生变化 (比如文本变化或图片被另一个不同尺寸的图片所替代)
    5. 页面一开始渲染的时候 (这个无法避免)
    6. 因为回流是根据视口的大小来计算元素的位置和大小的,所以浏览器的窗口尺寸变化也会引发回流…
  2. reflow 非常耗时,浏览器为了提升性能,对 JS连续 导致 reflow 的代码,把 reflow 的时间点延迟到结束后进行,但在此过程中,如果遇到了获取尺寸和位置的代码,浏览器会迫不得已立即 reflow

  3. 如何避免 DOM 的回流:

    1. 放弃传统操作 dom 的时代,基于 vue/react 开始数据影响视图模式,mvvm、mvc、virtual dom、dom diff 等;
    2. 分离读写操作(现代的浏览器都有渲染队列的机制);
      //(1)
      let box = document.getElementById('box');
      box.style.width = '200px'; 
      box.style.height = '200px';
      box.style.margin = '10px'; 
      // 因为浏览器存在渲染队列机制,如果引发回流的语句挨在一起写,只会引发一次回流
      
      // (2)
      box.style.width = '100px'
      box.style.height = '200px'
      box.clientHeight; // 读取高度,导致强行 reflow
      box.style.left = '10px'
      box.style.top = '10px'
      // 中间插入非引发回流语句,打断了任务队列,所以总共回流 2 次
      
    3. 样式集中改变;
    4. 缓存布局信息 (不要频繁读取 dom,会导致强制回流 Reflow)
    5. 元素批量修改;
      // 1. 文档碎片 createDocumentFragment
      let frag = document.createDocumentFragment();
      for (let i = 0; i < 10; i++) {
        let span = document.createElement('span');
        frag.appendChild(span);
      }
      navBox.appendChild(frag);
      
      // 2. 模板字符串拼接
      let str = ``;
      for (let i = 0; i < 10; i++) {
        str += `<span></span>`;
      }
      navBox.innerHTML = str;
      

DOM 的重绘(Repaint)

  1. 浏览器一边 reflow,一边进行生成对应的图形绘制到页面,绘制的过程称之为 repaint

  2. 所有会导致 reflow 的代码,均会导致 repaint

  3. 绘制的过程是靠 GPU 完成的,速度非常快,因此 相对于导致 reflow 的代码,repaint 的代码效率会高出很多

  4. 凡是不会影响盒子排列,仅影响盒子外观的代码都不会导致 reflow,仅导致 repaint,例如:

    • 改变背景颜色
    • 改变字体颜色
    • 圆角边框
    • 背景图
打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. 浏览器🧑‍💻 浏览器的渲染流程
  2. 2. DOM 的回流(Reflow)
  3. 3. DOM 的重绘(Repaint)