重排与重绘

当DOM的变化引起了元素的几何属性发生变化,浏览器不得不重新计算元素的几何属性,并重新构建渲染树,这个过程称为重排。注意这里至少会有一次重排-初始化页面布局。

由于节点的几何属性发生改变或者由于样式发生改变,例如改变元素背景色时,屏幕上的部分内容需要更新。这样的更新被称为重绘

 

由于浏览器渲染界面是基于流式布局模型的,也就是某一个DOM节点信息更改了,就需要对DOM结构重新进行计算,重新布局界面在,再次引发重排。

引起重排的操作有:

(1)页面首次渲染

(2)浏览器窗口大小发生变化(resize事件发生时)

(3)元素尺寸(大小,外边距,边框)或位置发生改变,或使用动画

(4)元素内容变化

(5)元素字体大小变化

(6)添加或删除可见的DOM元素

(7)设置style属性

(8)读取某些元素属性(offsetLeft/Top/Height/Width)

重排一定会引起重绘,但是重绘不一定会引起重排。

  当DOM结构发生变化时,例如节点的增减、移动等,也会触发重排。浏览器引擎布局的过程,类似于树的先序遍历,是一个从上到下从左到右的过程。通常在这个过程中,当前元素不会再影响其前面已经遍历过的元素,所以,如果在body最前面插入一个元素,会导致整个文档的重新渲染;而在其后插入一个元素,则不会影响到前面的元素。

 

如何减少重排次数?

(1)避免设置大量的style属性,因为通过设置style属性改变节点样式的话,每一次设置都会触发一次reflow,所以最好是使用class属性

(2)将需要多次重排的元素,position属性设置为absolute或fixed,这样元素就会脱离文档流,它的变化不会影响到其他元素。例如有动画效果的元素最好设置为绝对定位。

(3)由于display属性为none的元素不在渲染树中,对隐藏的元素操作不会引发其他元素的重排。如果对一个元素进行复杂的操作时,可以先隐藏他,操作完成之后再显示。这样只在隐藏和显示时触发两次重排,但是这可能导致浏览器的闪烁。

         这个会在显示与隐藏节点的时候,产生两次重绘。

function appendDataToElement(appendToElement,data){
    let li;
    for(let i=0;i<data.length;i++){
        li=document.createElement('li');
        li.textContent='text';
        appendToElement.appendChild(li);
    }
}
const ul=document.getElementById('list');
ul.style.display='none';
appendDataToElement(ul,data);
ul.style.display='block';

 

(4)不要把DOM节点的属性值放在循环里当成循环里的变量,例如改变DOM的内容,先定义一个变量,最后再添加到DOM上。

var position=document.getElementById('position');
var jobHTML='';
for(var i=0;i<jobArr.length;i++){
    jobHTML+='<option value='+i+'>'+jobArr[i]+'</option>';               
}
position.innerHTML+=jobHTML;

 

(5)使用文档片段在当前DOM之外构建一颗子树,再把它拷贝回文档

const ul = document.getElementById('list');
const fragment = document.createDocumentFragment();
appendDataToElement(fragment, data);
ul.appendChild(fragment);

 

posted @ 2018-03-26 17:04  安xiao曦  阅读(307)  评论(0编辑  收藏  举报