浏览器底层渲染机制2

回流(Reflow)/重排

页面第一次渲染完后,我们后期基于某些操作,修改了某个节点在视口中(自己所在层级中)的位置或者大小
这样浏览器需要重新计算当前视口(当前层级中)所有节点的布局位置「也就是把Layout操作重新搞了一遍」,
然后重新进行Painting绘制,我们把这个操作称之为"回流(Reflow)或者叫做重排"!回流非常消耗页面性能,
我们常说的操作DOM消耗性能,指的就是这件事!

哪些操作会引发回流?

  • 改变节点的位置
  • 改变节点的大小
  • 新增或者移除节点
  • 视口大小改变
  • 内容改变引发了节点的大小改变

而且回流一定会引发重绘,而且页面第一次渲染,本身就会有一次Layout和Painting

某些对于DOM操作(例如:改变文字颜色、背景、visibility「修改display可能会引发回流,但是设置visibility原始位置不动,则不会引发回流」...),并不会对节点的位置产生影响,此时只需要"重绘(Repaint)"即可!

在页面运行时的性能优化

前端性能优化的核心操作:减少操作DOM产生的回流(或重排)

@1 读写分离:把设置元素样式代码和获取元素样式代码分离编写,不要穿插混合一起

渲染队列机制:当代浏览器的机制,当前上下文代码执行过程中,遇到修改元素样式(操作DOM)的代码,浏览器并没有立即去处理,而是先存放在渲染队列中;当遇到获取元素样式操作(或者当前上下文执行完毕),才会刷新渲染对列(也就是把对列中对DOM的操作统一进行处理),引发一次回流!

     box.style.width='200px';
     box.style.height='300px';
     console.log(box.offsetWidth);
     console.log(box.offsetHeight);


     let w=box.offsetWidth;
     let h=box.offsetHeight;
     box.style.width=w + 10 + 'px';
     box.style.height=h + 10 + 'px';

@2 统一修改样式

  • 把需要修改的样式先写在样式表中,基于修改元素的样式类名达到修改样式的需求,也只会引发一次回流
    box.classList.add('active');
  • 基于cssText处理
    box.style.cssText='width:200px;height:300px';

@3 新增DOM元素采取"批量统一增加"的方案

  • 文档碎片:一个临时存储DOM节点的容器
  • let frag=document.createDocumentFragment(); //创建容器
    //fill 变成密集数组
    new Array(10).fill(null).forEach(()=>{
      let box=document.createElement('div');
      box.innerHTML='...';
      frag.appendChild(box); //把每一次创建的div先存放在文档碎片中
    });
    document.body.appendChild(frag); // 最后把容器插入到body末尾
  • 模板字符串拼接 

@4

修改元素的样式尽可能使用 transform 变形属性 / opacity,因为它的改变不会引发DOM回流「因为浏览器内部对其做了硬件加速,也可以理解为这就是"规定"」

@5

修改样式的元素,尽可能在单独的文档流中,虽然这样不能减少DOM的回流次数,但是可以让本次回流处理的更快,因为只需要把当前的文档流中的节点重新布局即可!渲染绘制的时候也只对当前文档流处理即可!

@6

JS处理动画的规则:

能用CSS3动画解决的,坚决不用JS动画,如果JS也解决不了,那就换需求! 适当情况下,需要牺牲平滑度来换取速度

不要直接自己操作DOM,使用Vue/React框架,我们只操作数据,操作DOM的事情交给框架去做即可!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值