zoukankan      html  css  js  c++  java
  • DOM操作优化

    文档对象模型 (DOM)是一个独立于特定语言的应用程序接口。

    1:在浏览器中,DOM是以javascript实现的,通过javascript来操作浏览器页面的元素。

    2:DOM提供了丰富的接口,但是DOM操作代价很高。

    3:页面前端代码的性能瓶颈大多集中在DOM操作上。

    4:前端性能优化主要关注点是DOM操作优化。

    5:DOM操作优化总原则是尽量减少DOM操作。

    DOM操作为什么会影响性能。

    1:DOM的实现和ECMAscript的实现是分离的。  

    --IE中,ECMAscript的实现在jscript.dll中,而DOM的实现在mshtml.dll中

    --Chrome中,ECMAscript的实现在V8引擎中,而DOM的实现在webkit中的webCore。

    其他浏览器类似,所以通过javascript 代码调用DOM借口,相当于两个独立模块的交互,相比较在同一模块的调用,这种跨模块调用性能损耗很高。(但是DOM操作对性能影响最大的还是浏览器的repaint 和reflow 重绘和重排)。

    简述下浏览器渲染原理:从下载文档到渲染页面的过程中

    1:浏览器会通过解析HTML文档来构建DOM树

    2:解析CSS产生CSS规则树

    3:解析js代码,这可能会修改生成的DOM树和CSS规则树

    4:根据DOM树和CSS树构建渲染树(css会根据选择器匹配HTML元素)

    5:渲染树包含每个元素的大小,边距等样式属性,不包含隐藏元素,head等不可见元素。

    6:浏览器根据元素的坐标和大小来计算每个元素的位置,并绘制这些元素到页面上。

    7:重绘是指页面的某些部分要重新绘制,比如颜色或者背景色,但是元素的位置和尺寸并没改变。

    8:重排是指元素的位置或者尺寸发生改变,浏览器需要重新计算渲染树,导致渲染树一部分或者全部发生变化。渲染树重新建立后,浏览器会重新绘制页面上受影响的元素。

    9:重排比重绘的代价高很多。

    现代浏览器会针对重绘和重排做性能优化,比如,把DOM操作积累一批后统一做一次重排或重绘。但有些情况浏览器会立即重排或重绘,比如:请求DOM元素布局信息:

    offsetTop/Left/Width/Height、scrollTop/Left/Width/Height、clientTop/Left/Width/Height、getComputedStyle()、currentStyle.这些值都是动态计算的,所以浏览器需要尽快完成页面的绘制,然后计算返回值,从而打乱了重排或重绘的优化。

    重排和重绘是不可避免的,但是可以降低他们带来的影响:

    1: 合并多次DOM操作。

    1 for(...){
    2   document.getElementById('ele').innerHTML="a_string";
    3 }
    4 
    5 for(...){
    6    arr[].push 
    7 }

    2:把DOM元素离线或者隐藏后修改。(适合需要那些大批量修改DOM元素的情况)

    (2.1):使用文档片段。

      --文档片段是一个轻量级的document对象。

           --不会和特定页面关联。

      --通过在文档片段上进行DOM操作可降低DOM操作对页面性能影响。

      --操作完成后附加在页面中。

      --对页面性能影响只存在于最后把文档片段附加到页面这一步操作上。

    1 var fragment = document.createDocumentFragment();
    2 //基于fragment的大量DOM操作
    3 document.getElementById('myEle').appendChild(fragment);

    (2.2):设置DOM元素的display样式为none来隐藏元素。

      --通过隐藏DOM元素,达到在页面中移除元素的效果。

      --经过大量的DOM操作后恢复元素原来的display样式。

    1 var myEle = document.getElementById("myEle");
    2 myEle.style.display="none";
    3 //基于myEle的大量的DOM操作
    4 myEle.style.display="block";

    (2.3):克隆DOM元素到内存中。

      --把页面的DOM元素克隆一份到内存中。

      --再在内存中操作克隆的元素。

      --操作完成后用此克隆的元素替代页面中原来的DOM元素。

    1 var old = document.getElementById('myEle');
    2 var clone = old.cloneNode(true);
    3 //一些基于clone的大量DOM操作
    4 old.parentNode.prelaceChild(clone,old);

    现代浏览器中因为有DOM操作优化,所以应用如上方式可能不能明显感受到性能改善,但是仍有市场的旧浏览器中,应用以上者三种编码方式可大幅提高页面渲染性能。

    3:设置具有动画效果的DOM元素的position属性为fixed或absolute。

      --设置动画效果的元素为绝对定位

      --使元素脱离页面布局流

      --避免频繁的重排,只涉及动画元素自身的重排。

      --可提高动画效果的展示性能。

     如果把动画设为绝对定位不符合要求,那可以在动画开始时设为绝对定位,等动画结束后恢复原始的定位设置。

    4:谨慎取得DOM元素的布局信息。

      --获取DOM元素的布局信息会强制浏览器刷新渲染树,并可能会导致页面的重排或重绘。

      --如果需要这些布局信息,最好是在DOM操作之前就取得。

    1 var newWidth = div1.offsetWidth+10;
    2 div1.style.width = newWidth +'px';
    3 
    4 var newHeight = div2.offsetHeight + 10;
    5 div2.style.Height = newHeight +'px';

    代码在遇到取得DOM元素信息时会触发页面重新计算渲染树,所以上边代码会导致页面重排两次,如果把取得的DOM元素布局信息提前,因为浏览器会优化连续的DOM操作,所以实际上只会有一次的页面重排出现。

    1 var newWidth=div1.offsetWidth+10;
    2 var newHeight = div2.offsetHeight+10;
    3 
    4 div1.style.width = newWidth+"px";
    5 div2.style.height = newHeight + "px";

    5:事件托管的方式来绑定事件。

      --DOM元素绑定事件会影响页面性能。一方面,绑定事件本身会占用处理时间,另一方面,浏览器保存事件绑定会占用内存。

      --页面元素绑定的事件越多,占用的处理时间和内存就越大。性能越差。

      --页面绑定的事件越少越好。

      --优雅的解决方法是事件托管方法(利用事件冒泡机制,只在父元素上绑定事件处理,用于所有子元素的事件,在事件处理函数中根据传入的参数判断事件源元素,针对不同的源元素做不同的处理,这样就不需要给每个子元素都绑定事件了。)

      --可以很方便的添加或删除子元素,不需要考虑因子元素移除或改动而需要修改事件绑定。

    1 document.getElementById('list').addEventListener("click", function(e){
    2      //检查事件源元素
    3      if(e.target && e.target.nodeName.toUpperCase() == "LI"){
    4          //针对子元素的处理
           console.log("clicked"+e.target.innerHTML);
    5 } 6 })

    上边的代码里,只在父元素绑定了click事件。当点击子节点时,click事件会冒泡,父节点捕捉事件后通过e.target检查事件源元素并做相应处理。但是事件绑定方式存在浏览器兼容问题。所以在很多框架提供了接口方法用于事件托管。比如 Jquery

    1 $("table").on("click","td",function(){
    2      $(this).toggleClass("chosen");
    3 });
  • 相关阅读:
    Oracle 冷备份详解【实战案例】
    Oracle Procedure记录
    【基础操作】1.表操作
    Oracle的基本语法,存储函数及触发器
    有志者事竟成 — 雷林鹏
    Les13 性能管理
    SharePoint 2010 创建联系人列表和使用联系人列表
    在SharePoint 2010中创建联系人Web数据库网站
    C#中数组如何赋值
    What Can Happen When You Try to Convert a Standard SharePoint 2010 Farm to Enterprise
  • 原文地址:https://www.cnblogs.com/ming-os9/p/8932370.html
Copyright © 2011-2022 走看看