重排重绘

当在浏览器输入url时,先问dns要IP,然后向该IP地址要资源,拿到所有资源(html,css,js...),首先构造dom-tree,style-tree,构造完后构造渲染树 render-tree,之后开始渲染展示


dom style render tree.png

说了这么多,那么什么是重排重绘呢,当修改容器大小位置等,会造成dom重排,重排后会重新构造render-tree,然后重绘,也就是说重排后一定会重绘。当修改样式时,会造成style-tree重绘

反复的修改容器空间或样式,会造成大量修改,因此需要优化。

单个节点

node.style.width = 30px
node.style.height= 30px
上述代码会造成俩次重排,重绘
$('node').css({width:30px;height:30px}) 只需要一次就ok了

或者要修改样式时,通过改变类名就能减少重排重绘
总结就是合并对节点的操作从而减少重排重绘

批量修改DOM

如向ul节点添加100个li节点。不考虑重排重绘可能产生一个li就插入,100次套餐跑不掉了
解决办法如下:

  1. display:none
    让ul节点脱离dom-tree 然后向ul插入li节点
    之后让ul display:block
    这种操作会造成俩次重排重绘,分别是脱离时,还原时

2.fragment 文档片段(碎片)
let fragment = document.createDocumentFragment()
for(100){//简写
fragment.append(li)
}
ul.appendchild(fragment)
这种操作只有一次重排重绘,插入时,且fragment节点不会被插入

看完fragment有人可能会想到下面的方法:
先copy源节点保存,操作完后向源节点的父节点替代源节点
let old = document.querySelector('#mylist');
let clone = old.cloneNode(true);
appendNode(clone, data);
old.parentNode.replaceChild(clone, old);
可以看到这种方法也是只有一次重排。总的来说,使用文档片段,可以操作更少的DOM(对比使用克隆节点),最小化重排重绘次数。

缓存布局信息

缓存布局信息这个概念,在《高性能JavaScript》DOM性能优化中,多次提到类似的思想,比如我现在要得到页面ul节点下面的100个li节点,最好的办法就是第一次获取后就保存起来,减少DOM的访问以提升性能,缓存布局信息也是同样的概念。前面有讲到,当访问诸如offsetLeft,clientTop这种属性时,会冲破浏览器自有的优化————通过队列化修改和批量运行的方法,减少重排/重绘版次。所以我们应该尽量减少对布局信息的查询次数,查询时,将其赋值给局部变量,使用局部变量参与计算。
看以下样例:
将元素div向右下方平移,每次移动1px,起始位置100px, 100px。性能糟糕的代码:

div.style.left = 1 + div.offsetLeft + 'px';
div.style.top = 1 + div.offsetTop + 'px';
这样造成的问题就是,每次都会访问div的offsetLeft,造成浏览器强制刷新渲染队列以获取最新的offsetLeft值。更好的办法就是,将这个值保存下来,避免重复取值

current = div.offsetLeft;
div.style.left = 1 + ++current + 'px';
div.style.top = 1 + ++current + 'px';

参考链接:https://segmentfault.com/a/1190000016990089

你可能感兴趣的:(重排重绘)