• 【javascript基础】Repaint 和 Reflow


    Repaint又叫Redraw,重绘,它是指一种不影响当前dom结构的和布局的一种重绘动作。

    以下的动作都会促发Repaint:

    1. 不可见或可见(visibility);
    2. 颜色和图片改变(background,border-color,color之类的属性);
    3. 不改变页面元素大小,形状和位置,但改变其外观的变化。

    Reflow,又叫重构, 比起 Repaint 来讲就是一种更加显著的变化了。它主要发生在 DOM 树被操作的时候,任何改变 DOM 的结构和布局都会产生 Reflow。但一个元素的 Reflow 操作发生时,它的所有父元素和子元素都会发生 Reflow,最后 Reflow 必然会导致 Repaint 的产生。举例说明,如下动作会产生 Repaint 动作:

    1. 浏览器窗口的变化;
    2. DOM 节点的添加删除操作;
    3. 一些改变页面元素大小,形状和位置的操作的触发。

    减少 Reflow

    通过 Reflow 和 Repaint 的介绍可知,每次 Reflow 比其 Repaint 会带来更多的资源消耗,我们应该尽量减少 Reflow 的发生,或者将其转化为只会触发 Repaint 操作的代码。

    参考如下代码:

     var pDiv = document.createElement(“div”); 
     document.body.appendChild(pDiv);----- reflow
     var cDiv1 = document.createElement(“div”); 
     var cDiv2 = document.createElement(“div”); 
     pDiv.appendChild(cDiv1);----- reflow
     pDiv.appendChild(cDiv2);----- reflow

    这是我们经常接触的代码了,但是这段代码会产生 3 次 reflow。再看如下代码:

    var pDiv = document.createElement(“div”); 
     var cDiv1 = document.createElement(“div”); 
     var cDiv2 = document.createElement(“div”); 
     pDiv.appendChild(cDiv1); 
     pDiv.appendChild(cDiv2); 
     document.body.appendChild(pDiv);----- reflow

    这里便只有一次 reflow,所以我们推荐这种 DOM 节点操作的方式。

    关于上述较少 Reflow 操作的解决方案,还有一种可以参考的模式:

    var pDiv = document.getElementById(“parent”); 
     pDiv.style.display = “none”----- reflow
    
     pDiv.appendChild(cDiv1); 
     pDiv.appendChild(cDiv2); 
     pDiv.appendChild(cDiv3); 
     pDiv.appendChild(cDiv4); 
     pDiv.appendChild(cDiv5); 
     pDiv.style.width = “100px”; 
     pDiv.style.height = “100px”; 
    
     pDiv.style.display = “block”----- reflow
                

    先隐藏 pDiv,再显示,这样,隐藏和显示之间的操作便不会产生任何的 Reflow,提高了效率。

    特殊测量属性和方法

    DOM 元素里面有一些特殊的测量属性的访问和方法的调用,也会触发 Reflow,比较典型的就是“offsetWidth”属性和“getComputedStyle”方法。

    图 1. 特殊测量属性和方法
    图 1. 特殊测量属性和方法 

    这些测量属性和方法大致有这些:

    • offsetLeft
    • offsetTop
    • offsetHeight
    • offsetWidth
    • scrollTop/Left/Width/Height
    • clientTop/Left/Width/Height
    • getComputedStyle()
    • currentStyle(in IE))

    这些属性和方法的访问和调用,都会触发 Reflow 的产生,我们应该尽量减少对这些属性和方法的访问和调用,参考如下代码:


    清单 19. 特殊测量属性

    				 
     var pe = document.getElementById(“pos_element”); 
     var result = document.getElementById(“result_element”); 
     var pOffsetWidth = pe.offsetWidth;
     result.children[0].style.width  = pOffsetWidth; 
     result.children[1].style.width  = pOffsetWidth; 
     result.children[2].style.width  = pOffsetWidth; 
    …………其他修改…………
    

    这里我们可以用临时变量将“offsetWidth”的值缓存起来,这样就不用每次访问“offsetWidth”属性。这种方式在循环里面非常适用,可以极大地提高性能。

    样式相关

    我们肯定经常见到如下的代码:

    清单 20. 样式相关

    				 
     var sElement = document.getElementById(“pos_element”); 
     sElement.style.border = ‘ 1px solid red ’
     sElement.style.backgroundColor = ‘ silver ’
     sElement.style.padding = ‘ 2px 3px ’
     sElement.style.marginLeft = ‘ 5px ’
    			

    但是可以看到,这里的每一个样式的改变,都会产生 Reflow。需要减少这种情况的发生,我们可以这样做:

    解决方案 1:


    清单 21. className 解决方案

    				 
     .class1 { 
     border: ‘ 1px solid red ’
     background-color: ‘ silver ’
     padding: ‘ 2px 3px ’
     margin-left: ‘ 5px ’
     } 
     document.getElementById(“pos_element”).className = ‘class1’ ;
    			

    用 class 替代 style,可以将原有的所有 Reflow 或 Repaint 的次数都缩减到一个。

    解决方案 2:


    清单 22. cssText 解决方案

    				 
     var sElement = document.getElementById(“pos_element”); 
     var newStyle = ‘ border: 1px solid red; ’ + ‘ background-color: silver; ’ + 
                                     ‘ padding: 2px 3px; ’ + “margin-left: 5px;”
     sElement.style.cssText += newStyle;
    			

    一次性设置所有样式,也是减少 Reflow 提高性能的方法。

  • 相关阅读:
    DragDrop 注册失败的问题
    《精通.NET互操作:P/Invoke,C++ Interop和COM Interop》推荐的工具列表
    勇于探索,及时总结,拥有自信!个人工作感受总结篇……
    C#4.0新特性对.NET互操作的影响(转载)
    UCHome: IP控制
    UCHome: SQL注入式攻击
    Windows下Cygwin模拟GCC开发
    序列化和反序列化
    UCHome: 解读common.php(转)
    UCHome: 提交检查
  • 原文地址:https://www.cnblogs.com/sniper007/p/2831328.html
Copyright © 2020-2023  润新知