重繪和重排

DOM樹:表示頁面結(jié)構(gòu)。
渲染樹:表示DOM節(jié)點(diǎn)如何顯示。

定義

當(dāng)DOM元素影響了元素的幾何屬性(例如寬和高),瀏覽器需要重新計(jì)算元素的幾何屬性,同樣其它元素的幾何屬性也會和位置也會因此受到影響。瀏覽器會使渲染樹中受到影響的部分失效,并重新構(gòu)造渲染樹。這個(gè)過程稱為“重排”。
完成重排后,瀏覽器會重新繪制受影響的部分到屏幕上中,該過程稱為“重繪”。

  • 重排發(fā)生的情況:
  1. 添加或刪除可見的DOM元素。
  2. 元素位置改變。
  3. 元素的尺寸改變(包括:內(nèi)外邊距、邊框厚度、寬度、高度等屬性的改變)。
  4. 內(nèi)容改變。
  5. 頁面渲染器初始化。
  6. 瀏覽器窗口尺寸改變。
  • 重繪發(fā)生的情況:
    重繪發(fā)生在元素的可見的外觀被改變,但并沒有影響到布局的時(shí)候。比如,僅修改DOM元素的字體顏色(只有Repaint,因?yàn)椴恍枰{(diào)整布局)
優(yōu)化辦法
  • fragment元素的應(yīng)用
    <ul id='fruit'>
    <li> apple </li>
    <li> orange </li>
    </ul>
    如果代碼中要添加內(nèi)容為peach、watermelon兩個(gè)選項(xiàng),你會怎么做?
    傳統(tǒng)做法:
    var lis = document.getElementById('fruit');
    var li = document.createElement('li');
    li.innerHTML = 'peach';
    lis.appendChild(li);

     var li = document.createElement('li');
     li.innerHTML = 'watermelon';
     lis.appendChild(li);
    

很容易想到如上代碼,但是很顯然,重排了兩次。隱藏的元素不在渲染樹中,太棒了,我們可以先把id為fruit的ul元素隱藏,然后添加li元素,最后再顯示,但是實(shí)際操作中可能會出現(xiàn)閃動,原因這也很容易理解。這時(shí),fragment元素就有了用武之地了。
var fragment = document.createDocumentFragment();

    var li = document.createElement('li');
    li.innerHTML = 'peach';
    fragment.appendChild(li);

    var li = document.createElement('li');
    li.innerHTML = 'watermelon';
    fragment.appendChild(li);

    document.getElementById('fruit').appendChild(fragment);

文檔片段的一個(gè)便利的語法特性是當(dāng)你附加一個(gè)片斷到節(jié)點(diǎn)時(shí),實(shí)際上被添加的是該片斷的子節(jié)點(diǎn),而不是片斷本身。只觸發(fā)了一次重排,而且只訪問了一次實(shí)時(shí)的DOM。

  • 緩存布局信息
    例如myElement元素沿對角線移動,每次移動一個(gè)像素。到500*500像素的位置結(jié)束。timeout循環(huán)體中可以這么做
    myElement.style.left = 1 + myElement.offsetLeft + 'px';
    myElement.style.top = 1 + myElement.offsetTop + 'px';
    if(myElement.offsetLeft >= 500){
    stopAnimation();
    }
    顯然這種方法低效,每次移動都要查詢偏移量,導(dǎo)致瀏覽器刷新渲染隊(duì)列而不利于優(yōu)化。好的辦法是獲取一次起始位置的值,然后賦值給一個(gè)變量。如下
    var current = myElement.offsetLeft;
    current++;
    myElement.style.left = current + 'px';
    myElement.style.top = current + 'px';
    if(myElement.offsetLeft >= 500){
    stopAnimation();
    }
  • 讓元素脫離文檔流
    使用絕對位置定位頁面上的動畫元素,將其脫離文檔流。觸發(fā)一小區(qū)域的重繪。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容