我们知道,对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编程》

高性能javascript学习总结(2)--DOM编程的更多相关文章

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

    参考 高性能javascript 文档对象模型(DOM)是独立于语言的,用于操作XML和HTML文档的程序接口API,在浏览器中主要通过DOM提供的API与HTML进行交互,浏览器通常会把DOM和ja ...

  2. javascript学习 真正理解DOM脚本编程技术背后的思路和原则

    本文学习来源于<javascriptDOM编程艺术>仅作笔记 学会怎样才能利用DOM脚本编程技术以一种既方便自己更体贴用户的方式去充实和完善你们的网页. 循序渐进:从最核心的内容开始,逐步 ...

  3. 高性能javascript学习笔记系列(5) -快速响应的用户界面和编程实践

    参考高性能javascript 理解浏览器UI线程  用于执行javascript和更新用户界面的进程通常被称为浏览器UI线程  UI线程的工作机制可以理解为一个简单的队列系统,队列中的任务按顺序执行 ...

  4. 高性能javascript学习笔记系列(1) -js的加载和执行

    这篇笔记的内容主要涉及js的脚本位置,如何加载js脚本和脚本文件执行的问题,按照自己的理解结合高性能JavaScript整理出来的 javascript是解释性代码,解释性代码需要经历转化成计算机指令 ...

  5. JavaScript(三)-- DOM编程

    JavaScript编程中最基本的就是DOM编程,DOM是 Document Object Model文本对象模型,就是对DOM对象进行编程的过程. Java语言和Js都有针对于DOM的编程,两者类似 ...

  6. 高性能javascript学习总结(3)--数据访问

    在 JavaScript 中,数据存储位置可以对代码整体性能产生重要影响.有四种数据访问类型:直接量,变量,数组项,对象成员.         直接量仅仅代表自己,而不存储于特定位置. JavaScr ...

  7. 高性能javascript学习笔记系列(6) -ajax

    参考 高性能javascript javascript高级程序设计 ajax基础  ajax技术的核心是XMLHttpRequest对象(XHR),通过XHR我们就可以实现无需刷新页面就能从服务器端读 ...

  8. 高性能javascript学习笔记系列(4) -算法和流程控制

    参考高性能javascript for in 循环  使用它可以遍历对象的属性名,但是每次的操作都会搜索实例或者原型的属性 导致使用for in 进行遍历会产生更多的开销 书中提到不要使用for in ...

  9. 高性能javascript学习笔记系列(2)-数据存取

    参考 高性能javascript Tom大叔深入理解javascript系列 相关概念 1.执行上下文   当控制器转到ecmascript可执行代码的时候,就会进入一个执行上下文,执行上下文是以堆栈 ...

随机推荐

  1. react-native 详解

    1.获取主屏幕尺寸 // 导入类库 var Dimensions = require('Dimensions'); // 样式 const styles = StyleSheet.create({ c ...

  2. axios 处理并发请求

    //同时发起多个请求时的处理 axios.all([get1(), get2()]) .then(axios.spread(function (res1, res2) { // 只有两个请求都完成才会 ...

  3. WIN10 当中装BDM驱动

      方法: 禁用第三方签名 将插件替换原有的dll   1.参考此篇文档 http://jingyan.baidu.com/article/375c8e19c2b25b25f2a229a3.html ...

  4. iOS代码覆盖率测试工具

    基于lcov-1.11的:CodeCoverage4iOS   阅读目录 环境准备 Xcode工程配置 构建并安装程序 收集代码覆盖率 过滤结果 合并多个Coverage.info⽂件⽣成覆盖率报告: ...

  5. 正则化--Lambda

    模型开发者通过以下方式来调整正则化项的整体影响:用正则化项的值乘以名为 lambda(又称为正则化率)的标量.也就是说,模型开发者会执行以下运算: $$\text{minimize(Loss(Data ...

  6. js正则表达式的分组提取

  7. PHP面试题及答案解析(6)—PHP网络编程

    1.禁用COOKIE后SEESION还能用吗? 可以,COOKIE和SESSION都是用来实现会话机制的,由于http协议是无状态的,所以要想跟踪一个用户在同一个网站之间不同页面的状态,需要有这么一个 ...

  8. 使用OSChina代码托管管理项目(四)

    本篇主要介绍使用Eclipse的Egit插件克隆远程project到本地的操作步骤 一.在Git资源库管理视图中新建一个远程资源库位置 点击红框中button进行加入 二.输入远程资源库相关信息.选择 ...

  9. opencv--python--anaconda----contrib 安装

    https://pypi.python.org/pypi/opencv-python/3.4.0.12 https://pypi.python.org/pypi?%3Aaction=search&am ...

  10. centos 防火墙开放80端口

    辛辛苦苦编译安装完Ngnix,mysql ,PHP,后发现不能访问,后来发现是防火墙把80端口给禁用了.开启之:(以下参考自:http://llhdf.javaeye.com/blog/526176) ...