• 高性能javascript学习笔记系列(3) -DOM编程


    参考 高性能javascript

    文档对象模型(DOM)是独立于语言的,用于操作XML和HTML文档的程序接口API,在浏览器中主要通过DOM提供的API与HTML进行交互,浏览器通常会把DOM和javascript独立实现,这意味着当我们通过javascript操作DOM的时候势必的产生性能上的开销,因此提升页面性能的的思路是尽可能的减少DOM操作或者优化DOM操作

    DOM的访问与修改

      (1)减少频繁的读取DOM元素

    (1)for(var i = 0;i < 10;i++) {
      document.getElementById("test") += "a";    
    }
    //上面的代码每次循环都进行了读取 
    (2)var content = ""; for(var i = 0;i < 10;i++) { content += "a"; } document.getElementById("test").innerHTML = content; //只有在最后一次通过innerHTML进行了读取 当我们更新一段html是使用innerHTML代替原始的dom操作

     (2)节点克隆

    当需要创建大量相似的节点的时候,通过element.clonenode()复制相应的节点,来代替重复的创建相应的节点来提升一部分的性能

    (3)处理HTML集合

    当我们通过document.getElementsByTagName()   document.getElementsByClassName() document.getElementsByName()  返回的是nodelist  它是一种类数组的集合,我们能通过下标的方式查找到集合中的元素

    同样的通过下面的属性得到的也是html集合 

    document.images document.links document.forms document.forms[0].elements

    操作html集合会出现性能的问题是html集合是维持实时的状态,也就是当你在文档中添加一个元素的时候,这个时候你在通过特定的方式获取html集合的长度的时候它的长度是实时变化的,html集合与文档处于连接的状态,获取html的信息的时候需要进行查询操作。

    处理html集合元素有大致两种方式:

    3.1将html集合转换成数组,因为遍历数组相对于遍历集合更快

      function toArray(coll) {
          for(var i = 0,a = [],length = coll.length;i < len;i++) {
            a[i] = coll[i];    
          }
          return a;
      } 

    3.2减少集合的查询操作,缓存局部变量

    function test(coll) {
      var length = coll.length;
      var id = "";
      for(var i = 0;i <length;i+=1) {
          var el = coll[i];
          id = el.getAttribute("id");
          console.log(id);
      }
    }

    (4)选取dom元素 

    4.1 使用能区分元素节点的选择API

    属性名 被替代的属性
    children childNodes
    childElementCount childNodes.length
    firstElementChild firstChild
    lastElementChild  lastChild
    nextElementSibling nextSibling
    previousElementSibling previousSibling

    上面的第一列属性只会返回相应的元素节点(两个节点之间的空格也会被识别成文本节点)  当我们通过第二列属性进行操作的时候,就需要在进行一步过滤的操作,增加了开销

    4.2 使用选择器API

    当需要进行大量的组合操作的时候,通过document.querySelectorAll()来进行元素的选择,通过这种方式获取的是一个nodelist,但它不与文档进行实时的更新,是一种静态的列表

    (5)重绘与重排

    当下载完页面的组件后,就会生成两个页面结构 DOM树  表示页面的结构  渲染树 表示DOM节点如何被显示   每一个在DOM树中需要被显示的元素在渲染树中至少存在一个对应的节点(在渲染树中的节点称为帧或者盒),当DOM的变化影响了元素的几何属性(宽高)的时候,这样浏览器就会重新计算元素的几何尺寸,其他元素的几何尺寸也会受到相应的影响,浏览器会使渲染树中受到影响的部分失效并重新构造渲染树,这个过程叫做重排,完成重排后浏览器重新绘制受到影响的部分,这个过程就叫做重绘

    重绘和重排都是代价昂贵的操作,所以优化的方案是最小化重绘和重排

    重排发生的时机

    •   添加或删除可见的DOM元素
    •   元素位置的改变
    •   元素尺寸的变化
    •   内容的改变(例如文本的改变或者图片内容的改变影响了元素的几何属性)
    •   页面渲染器的初始化
    •   浏览器窗口尺寸的改变

    浏览器会优化重排的过程,通过队列的方式修改并批量的执行重拍的过程,但是当我们使用一些属性或者方法的时候,会强制的刷新渲染队列触发重排,当我们频繁的进行这些操作的时候,就会造成性能的开销

    优化的思路:

    (1)集中操作  将设置样式和获取样式进行分离(不要在布局信息改变的时候去进行查询操作),并且尽可能的合并操作

    var el = document.getElementById("test");
    el.style.cssText = "border-left:1px;border-right:2px;border-bottom:3px;";

    (2)批量的修改DOM的时候,可以通过下面的方式减少重绘与重排    

    1. 使元素脱离文档流
    2. 对齐应用修改
    3. 将元素带回文档流

    脱离文档流的方案

    1. 隐藏元素 应用修改 显示元素
    2. 使用文档碎片(使用document.createDocumentFragment()创建的文档碎片添加到文档的时候,就将文档碎片的子节点进行添加而不是文档碎片本身)
    3. 将原始元素拷贝进行修改,然后替换元素元素

    (3)缓存布局信息 这个思路有点像处理集合元素的时候的方案,通过缓存局部的布局信息,能减少强制刷新渲染队列的次数,也就减少了重排

    (4)动画元素的处理 其实思路是一样的 动画有可能会造成大量其他元素位置改变,当动画开始的时候,让它脱离文档流,进行动画的展示,动画完结后让它回到文档流

  • 相关阅读:
    easyui accordion—手风琴格子始终展开和多个格子展开
    55分钟学会正则表达式
    解决github push错误The requested URL returned error: 403 Forbidden while accessing
    浅谈github页面域名绑定
    HighChartS cpu利用率动态图(Java版)
    easyUI——datebox验证和自定义取消按钮
    Linux下常用压缩格式的压缩与解压方法
    EasyUI修改DateBox和DateTimeBox的默认日期格式
    Highcharts的基本属性和方法详解
    Highcharts的基本属性和方法详解
  • 原文地址:https://www.cnblogs.com/tiantianwaigong/p/5550317.html
Copyright © 2020-2023  润新知