我们知道,对DOM的操作都是非常的耗性能的,那么为什么会耗性能呢?
     文档对象模型(DOM)是一个独立于语言的,使用 XML和 HTML 文档操作的应用程序接口(API)。在浏览器中,主要与 HTML 文档打交道,在网页应用中检索 XML 文档也很常见。DOM APIs 主要用于访问这些文档中的数据。尽管 DOM 是与语言无关的 API,在浏览器中的接口却是以 JavaScript 实现的。客户端大多数脚本程序与文档打交道,DOM 就成为 JavaScript 代码日常行为中重要的组成部分。 
一、重绘和重排版        
        当浏览器加载完所有页面 HTML标签,JavaScript,CSS之后,它开始解析文件并创建两个内部数据结构: 一棵 DOM 树表示页面结构 ;一棵渲染树表示 DOM 节点如何显示。渲染引擎首先解析HTML文档,转换为一棵DOM树,此为第一步。接下来不管是内联式,外联式还是嵌入式引入的CSS样式也会被解析,渲染出另 外一棵用于渲染DOM树的树-渲染树(render tree) ,渲染树包含带有颜色,尺寸等显示属性的矩形,这些矩形的顺序与显示顺序一致。渲染树中为每个需要显示的DOM树节点存放至少一个节点(隐藏 DOM 元素在渲染树中没有对应节)。渲染树上的节点称为“框”或者“盒”,符合 CSS 模型的定义,将页面元素看作一个具有填充、边距、框和位置的盒。一旦 DOM 树和渲染树构造完毕,浏览器就可以显示(绘制)页面上的元素了。 
        当 DOM 改变影响到元素的几何属性(宽和高)——例如改变了边框宽度或在段落中添加文字,将发生一系列后续动作——浏览器需要重新计算元素的几何属性,而且其他元素的几何属性和位置也会因此改变受到影响。浏览器使渲染树上受到影响的部分失效,然后重构渲染树。这个过程被称作重排版。重排版完成时,浏览器在一个重绘进程中重新绘制屏幕上受影响的部分。 
        不是所有的 DOM 改变都会影响几何属性。例如,改变一个元素的背景颜色不会影响它的宽度或高度。在这种情况下,只需要重绘(不需要重排版),因为元素的布局没有改变。 重绘和重排版是负担很重的操作,可能导致网页应用的用户界面失去响应。那么,什么时候会发生重排版呢?

        1、添加或删除可见的 DOM 元素 ;
        2、元素位置改变 ;
        3、元素尺寸改变(因为边距,填充,边框宽度,宽度,高度等属性改变);
        4、内容改变,例如,文本改变或图片被另一个不同尺寸的所替代 ;
        5、最初的页面渲染;
        6、浏览器窗口改变尺寸。
根据改变的性质,渲染树上或大或小的一部分需要重新计算。某些改变可导致重排版整个页面:例如,当一个滚动条出现时。 
         因为计算量与每次重排版有关,大多数浏览器通过队列化修改和批量显示优化重排版过程。然而,你可能(经常不由自主地)强迫队列刷新并要求所有计划改变的部分立刻应用。获取布局信息的操作将导致刷新队列动作,这意味着使用了下面这些方法: 
 • offsetTop, offsetLeft, offsetWidth, offsetHeight 
• scrollTop, scrollLeft, scrollWidth, scrollHeight 
• clientTop, clientLeft, clientWidth, clientHeight 
• getComputedStyle() (currentStyle in IE)(在 IE 中此函数称为 currentStyle) 
布局信息由这些属性和方法返回最新的数据, 所以浏览器不得不运行渲染队列中待改变的项目并重新排版以返回正确的值。
二、最小化重绘和重排版

var el = document.getElementById('mydiv');
el.style.borderLeft = '1px';
el.style.borderRight = '2px';
el.style.padding = '5px'; 

这里改变了三个风格属性,每次改变都影响到元素的几何属性。在这个糟糕的例子中,它导致浏览器重排版了三次。大多数现代浏览器优化了这种情况只进行一次重排版,但是在老式浏览器中,或者同时有一个分离的同步进程(例如使用了一个定时器),效率将十分低下。如果其他代码在这段代码运行时查询布局信息,将导致三次重布局发生。而且,此代码访问 DOM 四次,可以被优化。   一个达到同样效果而效率更高的方法是:将所有改变合并在一起执行,只修改 DOM 一次。可通过使用cssText 属性实现: 
var el = document.getElementById('mydiv');
el.style.cssText = 'border-left: 1px; border-right: 2px; padding: 5px;'; 

     另一个一次性改变风格的办法是修改 CSS 的类名称,而不是修改内联风格代码。这种方法适用于那些风格不依赖于运行逻辑,不需要计算的情况。改变 CSS 类名称更清晰,更易于维护;它有助于保持脚本免除显示代码,虽然它可能带来轻微的性能冲击,因为改变类时需要检查级联表。 
var el = document.getElementById('mydiv');
el.className = 'active'; 

三、批量修改 DOM 
        当你需要对 DOM 元素进行多次修改时,你可以通过以下步骤减少重绘和重排版的次数:
        1、从文档流中摘除该元素 ;
        2、对其应用多重改变;
        3、将元素带回文档中 。
此过程引发两次重排版——第一步引发一次,第三步引发一次。如果你忽略了这两个步骤,那么第二步中每次改变都将引发一次重排版。 
有三种基本方法可以将 DOM 从文档中摘除:
        1、隐藏元素,进行修改,然后再显示它;
var ul = document.getElementById('mylist');
ul.style.display = 'none';
appendDataToElement(ul, data);
ul.style.display = 'block'; 

        2、使用一个文档片断在已存 DOM 之外创建一个子树,然后将它拷贝到文档中;
var fragment = document.createDocumentFragment();
appendDataToElement(fragment, data);
document.getElementById('mylist').appendChild(fragment); 

        3、将原始元素拷贝到一个脱离文档的节点中,修改副本,然后覆盖原始元素。 
var old = document.getElementById('mylist');
var clone = old.cloneNode(true);
appendDataToElement(clone, data);
old.parentNode.replaceChild(clone, old); 

ps:以上内容总结于《高性能javascript编程》

转载于:https://www.cnblogs.com/jackyWHJ/p/3594434.html

高性能javascript学习总结(2)--DOM编程相关推荐

  1. javascript 学习 —— BOM和DOM编程学习

    这是我的第一个博客,用来记录自己的学习历程.之前的学习会在项目下写备注,再次翻看也有些不方便.从今天开始就用博客记录吧. 一.BOM ( browser object model ) 与DOM 1.在 ...

  2. JavaScript学习笔记之DOM篇,带你全面了解什么是DOM

    DOM在前面的JavaScript学习笔记(一)–JS基础里简单提到过,它是浏览器厂商提供的用来控制html / css 的代码的文档对象模型,是JavaScript的重要组成部分,现在带大家详细了解 ...

  3. JavaScript学习笔记(四)(DOM)

    JavaScript学习笔记(四) DOM 一.DOM概述 二.元素对象 2.1 获取方式 (1).通过ID获取一个元素对象,如果没有返回null (2).通过`标签名`获取一组元素对象,,如果没有返 ...

  4. 轻松学习JavaScript二十七:DOM编程学习之事件模型

    在介绍事件模型之前,我们先来看什么是事件和什么是event对象. 一事件介绍 JavaScript事件是由访问Web页面的用户引起的一系列操作,使我们有能力创建动态页面,事件是可以被 JavaScri ...

  5. 轻松学习JavaScript二十:DOM编程学习之获取节点

    我们这里所说的获取节点包含元素节点,属性节点和文本节点.通常,通过DOM我们就能够操作HTML元素.为 了做到这件事情,您必须首先找到该元素.W3C提供了比较方便简单的定位节点的方法和属性,以便我们快 ...

  6. javascript 学习笔记之面向对象编程(二):继承多态

    ~~接上篇~~上一篇实现了类的实现以及类成员变量和方法的定义,下面我们来了解下面向对象中两个最重要的特性:继承和多态. 继承 js中同样可以实现类的继承这一面向对象特性,继承父类中的所有成员(变量和属 ...

  7. JavaScript学习随记——面向对象编程(继承)

    @Example:基于原型链的继承 <!DOCTYPE HTML> <html><head><meta http-equiv="Content-Ty ...

  8. JavaScript学习笔记(BOM编程案例)

    文章目录 1.window中的open.close.alert.confirm方法 2.history和location 2.1 history中的back和go方法 2.2 location的hre ...

  9. javascript学习之利用DOM和正则表达式判断主流浏览器的类型

    火狐浏览器测试结果: 谷歌浏览器测试结果 IE8测试结果: IE11测试结果:

最新文章

  1. Android华容道之一步一步实现-5-图像块移动算法实现
  2. 32.生命周期注释.rs
  3. ajax类型的区别,ajax请求的类型 有post get 请问两种有何区别?
  4. 为什么那些每三年跳一次槽的人越跳越好? - 震撼
  5. python语言学习笔记整理
  6. (软件工程复习核心重点)第一章软件工程概论-第二节:软件工程
  7. Js 与 as 相互通信
  8. 湿气重的人,脸上会有哪些信号?
  9. Sublime Text编写80×86汇编.asm文件的语法高亮插件
  10. C#基础知识回顾整理
  11. ASP中常用的服务器检测源代码
  12. PHP排序算法之快速排序
  13. f3 fatfree小型php,F3-fatfree小型php框架教程(三)
  14. J2EE架构师路线脑图
  15. 微信小程序中相机api_微信拍照翻译, 使用小程序拍照翻译API功能
  16. 高一计算机算法教案,教科版 高一信息技术 必修1 第四单元 4.2 数值计算 教案...
  17. 20155313 2016-2017-2《Java程序设计》课程总结
  18. 巴菲特致股东的一封信:2004年
  19. 《正见——佛陀的证悟》读后感
  20. linux下Intel无线网卡驱动安装

热门文章

  1. 26 Socket Addressing and Client Socket Programming
  2. Pycharm TensorFolw配置
  3. 编程语言对比 内存操作
  4. opencv ORB角检测
  5. sip 时序图_Tcl与Design Compiler (五)——综合库(时序库)和DC的设计对象(下)
  6. java 线程安全原子性_Java 线程安全之原子性
  7. VMware vCenter Server6.5升级至6.7
  8. Redis学习总结(22)——Redis的主从复制是如何做的?复制过程中也会产生各种问题?
  9. 支付业务与技术架构学习总结(4)——对账相关业务知识及对账系统总结
  10. Java基础学习总结(50)——Java事务处理总结