zoukankan      html  css  js  c++  java
  • 重排和重绘

    重排:当DOM树变化影响了元素几何属性(宽、高等等)浏览器此时需要重新计算几何属性;并且页面其他元素的几何属性也受到了影响;这样渲染树就发生了变化;需要充排(reflow)

    重绘:当DOM的变化仅仅影响了背景色等等非几何属性;就发生了重绘;布局没有变化;

    触发重排: 页面初始渲染

                      添加、删除可见DOM元素

            改变元素位置

                      改变元素尺寸(宽、高、内外边距、边框等)

                      改变元素内容(文本或图片等)

                      改变窗口尺寸

    不同情况下重排的范围和程度会不同

    某些情况下甚至会发生整个页面、比如滑动滚动条

    浏览器优化:渲染队列 

      用js修改div样式       div.style.left='10px';

               div.style.top='10px';

               div.style.width='10px';

               div.style.height='10px';

           这样我们修改了元素的 left、top、width、height属性

           满足了发生重排的条件 。理论上会发生四次重排

           但是实际只发生了一次

           因为我们现代的浏览器都有渲染队列的机制

            当我改变了元素的一个样式会导致浏览器发生重排或者重绘时候

           它会进入一个渲染队列

            然后浏览器继续往下看,若果还有样式修改同样加入队伍

       直到没有样式修改

       浏览器会按照渲染队列批量执行来优化重排过程,一并修改样式

            把四次重排优化为一次

           

              但如果我们想在后台打印

            

              千万不要写这样的代码,因为发生了4次重排
              不懂了,不是说浏览器有渲染队列优化机制吗?
              为什么这样写就会发生4次重排
              因为offsetLeft/Top/Width/Height非常叼
              它们会强制刷新队列要求样式修改任务立刻执行
              想一想其实这么做是有道理的
              毕竟浏览器不确定在接下来的代码中你是否还会修改同样的样式
             为了保证获得正确的值,它不得不立刻执行渲染队列触发重排(错的不是我,是这个世界)

             

        以下属性或方法会刷新渲染队列

    •   offsetTop、offsetLeft、offsetWidth、offsetHeight
    •   clientTop、clientLeft、clientWidth、clientHeight
    •   scrollTop、scrollLeft、scrollWidth、scrollHeight
    •   getComputedStyle()(IE中currentStyle)

    元素批量修改

    现在我们想要向ul中循环添加大量li
    (如果ul还不存在,最好的办法是先循环添加li到ul,然后再把ul添加到文档,1次重排)

    var ul = document.getElementById('demo');
    for(var i = 0; i < 1e5; i++){
        var li = document.createElement('li');
        var text = document.createTextNode(i);
        li.appendChild(text);
        ul.appendChild(li);
    }

    我可以做出下面的优化

    var ul = document.getElementById('demo');
    ul.style.display = 'none'; <--
    for(var i = 0; i < 1e5; i++){
        var li = document.createElement('li');
        var text = document.createTextNode(i);
        li.appendChild(text);
        ul.appendChild(li);
    }
    ul.style.display = 'block'; <--
    var ul = document.getElementById('demo');
    var frg = document.createDocumentFragment(); <--
    for(var i = 0; i < 1e5; i++){
        var li = document.createElement('li');
        var text = document.createTextNode(i);
        li.appendChild(text);
        frg.appendChild(li); <--
    }
    ul.appendChild(frg); <--
    var ul = document.getElementById('demo');
    var clone = ul.cloneNode(true); <--
    for(var i = 0; i < 1e5; i++){
        var li = document.createElement('li');
        var text = document.createTextNode(i);
        li.appendChild(text);
        clone.appendChild(li); <--
    }
    ul.parentNode.replaceChild(clone,ul); <--

    上面的方法减少重绘和重排的原理很简单

        • 元素脱离文档
        • 改变样式
        • 元素回归文档

    而改变元素就分别使用了隐藏元素、文档碎片和克隆元素
    上面的方法我认为仅仅是理论上可以优化重排重绘次数
    现代浏览器的优化可能会超过我们的想象

          

  • 相关阅读:
    UVa 1151 Buy or Build【最小生成树】
    UVa 216 Getting in Line【枚举排列】
    UVa 729 The Hamming Distance Problem【枚举排列】
    HDU 5214 Movie【贪心】
    HDU 5223 GCD
    POJ 1144 Network【割顶】
    UVa 11025 The broken pedometer【枚举子集】
    HDU 2515 Yanghee 的算术【找规律】
    Java基本语法
    Java环境变量,jdk和jre的区别,面向对象语言编程
  • 原文地址:https://www.cnblogs.com/stone5/p/9041154.html
Copyright © 2011-2022 走看看