javascript之DOM优化

DOM访问和操作是现代网页应用中很重要的一部分。但每次你通过“桥梁”从ECMAScript到DOM时,都会被收取“过路费”。为减少DOM编程中的性能损失,具体要注意的有:

一。最小化DOM访问,在javascript端做尽可能多的事。

Js代码  

  1. function innerHTMLLoop() {
  2. for (var count = 0; count < 15000; count++) {
  3. document.getElementById(‘here‘).innerHTML += ‘a‘;
  4. }
  5. }
  6. function innerHTMLLoop2() {
  7. var content = ‘‘;
  8. for (var count = 0; count < 15000; count++) {
  9. content += ‘a‘;
  10. }
  11. document.getElementById(‘here‘).innerHTML += content;
  12. }

innerHTMLLoop2显然要比innerHTMLLoop更好。

二。在反复访问的地方使用局部变量存放DOM引用。

(此点结合第三点一起)

三。小心地处理HTML集合,因为他们表现出“存在性”,总是对底层文档重新查询。将集合length属性缓存到一个变量中,在迭代中使用这个变。如果经常操作这个集合,可以将集体拷贝到数组中。

Js代码  

  1. HTML集合有:
  2. document.getElementsByName()
  3. document.getElementsByClassName()
  4. document.getElementsByTagName_r()
  5. document.images
  6. document.links
  7. document.forms
  8. document.forms[0].elements

这些方法和属性返回HTMLCollection 对象,是一种类似数组的列表。它们不是数组(因为它们没有诸

如push()或slice()之类的方法),但是提供了一个length 属性,和数组一样你可以使用索引访问列表中的

元素。例如,document.images[1]返回集合中的第二个元素。正如DOM 标准中所定义的那样,HTML 集合

是一个“虚拟存在,意味着当底层文档更新时,

Js代码  

  1. var alldivs = document.getElementsByTagName_r(‘div‘);
  2. for (var i = 0; i < alldivs.length; i++) {
  3. document.body.appendChild(document.createElement(‘div‘))
  4. }
  5. 这段代码看上去只是简单地倍增了页面中div 元素的数量。它遍历现有div,每次创建一个新的div 并附
  6. 加到body 上面。但实际上这是个死循环,因为循环终止条件alldivs.length 在每次迭代中都会增加,它反
  7. 映出底层文档的当前状态。

将一个HTML集合拷贝给一个数组:

Js代码  

  1. function toArray(coll) {
  2. for (var i = 0, a = [], len = coll.length; i < len; i++) {
  3. a[i] = coll[i];
  4. }
  5. return a;
  6. }

Js代码  

  1. var coll = document.getElementsByTagName_r(‘div‘);
  2. var ar = toArray(coll);
  3. //slower
  4. function loopCollection() {
  5. for (var count = 0; count < coll.length; count++) {
  6. }
  7. }
  8. // faster
  9. function loopCopiedArray() {
  10. for (var count = 0; count < arr.length; count++) {
  11. }
  12. }
  13. // faster
  14. function loopCacheLengthCollection() {
  15. var coll = document.getElementsByTagName_r(‘div‘),
  16. len = coll.length;
  17. for (var count = 0; count < len; count++) {
  18. }
  19. }

一般来说,对于任何类型的DOM 访问,如果同一个DOM 属性或方法被访问一次以上,最好使用一个

局部变量缓存此DOM 成员。当遍历一个集合时,第一个优化是将集合引用存储于局部变量,并在循环之

外缓存length 属性。然后,如果在循环体中多次访问同一个集合元素,那么使用局部变量缓存它。

Js代码  

  1. // slow
  2. function collectionGlobal() {
  3. var coll = document.getElementsByTagName_r(‘div‘),
  4. len = coll.length,
  5. name = ‘‘;
  6. for (var count = 0; count < len; count++) {
  7. name = document.getElementsByTagName_r(‘div‘)[count].nodeName;
  8. name = document.getElementsByTagName_r(‘div‘)[count].nodeType;
  9. name = document.getElementsByTagName_r(‘div‘)[count].tagName;
  10. }
  11. return name;
  12. };
  13. // faster
  14. function collectionLocal() {
  15. var coll = document.getElementsByTagName_r(‘div‘),
  16. len = coll.length,
  17. name = ‘‘;
  18. for (var count = 0; count < len; count++) {
  19. name = coll[count].nodeName;
  20. name = coll[count].nodeType;
  21. name = coll[count].tagName;
  22. }
  23. return name;
  24. // fastest
  25. function collectionNodesLocal() {
  26. var coll = document.getElementsByTagName_r(‘div‘),
  27. len = coll.length,
  28. name = ‘‘,
  29. el = null;
  30. for (var count = 0; count < len; count++) {
  31. el = coll[count];
  32. name = el.nodeName;
  33. name = el.nodeType;
  34. name = el.tagName;
  35. }
  36. return name;
  37. };

四。可能的话,使用速度更快的API,诸如querySelectorAll()和firstElementChild

下列浏览器支持选择器API:Internet Explorer 8,Firefox 3.5,Safari 3.1,Chrome 1,Opera 10。

具体用法此处不详解。

五。注重重绘和重排版:批量修改风格,离线操作DOM树,缓存并减少对布局信息的访问。

当浏览器下载完所有页面HTML 标记,JavaScript,CSS,图片之后,它解析文件并创建两个内部数据

结构:一棵DOM树(表示页面结构),一棵渲染树(表示DOM节点如何显示)。

重排版的情况:

添加或删除可见的DOM元素

元素位置改变

元素尺寸改变(因为边距,填充,边框宽度,宽度,高度等属性改变)

内容改变,例如文本改变或图片被另一个不同尺寸的所替代

最初的页面渲染

浏览器窗口改变尺寸

(1)批量修改

重排版和重绘代价昂贵,所以,提高程序响应速度一个好策略是减少此类操作发生的机会。为减少发生

次数,你应该将多个DOM 和风格改变合并到一个批次中一次性执行。

Js代码  

  1. var el = document.getElementById(‘mydiv‘);
  2. el.style.borderLeft = ‘1px‘;
  3. el.style.borderRight = ‘2px‘;
  4. el.style.padding = ‘5px‘;
  5. //better
  6. var el = document.getElementById(‘mydiv‘);
  7. el.style.cssText = ‘border-left: 1px; border-right: 2px; padding: 5px;‘;
  8. 如果你打算保持当前的风格,你可以将它附加在cssText 字符串的后面。
  9. el.style.cssText += ‘; border-left: 1px;‘;
  10. //or
  11. var el = document.getElementById(‘mydiv‘);
  12. el.className = ‘active‘;

(2)离线操作DOM

Js代码  

  1. var data = [
  2. {
  3. "name": "Nicholas",
  4. "url": "http://nczonline.net"
  5. },
  6. {
  7. "name": "Ross",
  8. "url": "http://techfoolery.com"
  9. }
  10. ];
  11. //一个通用的函数,用于将新数据更新到指定节点中
  12. function appendDataToElement(appendToElement, data) {
  13. var a, li;
  14. for (var i = 0, max = data.length; i < max; i++) {
  15. a = document.createElement(‘a‘);
  16. a.href = data[i].url;
  17. a.appendChild(document.createTextNode(data[i].name));
  18. li = document.createElement(‘li‘);
  19. li.appendChild(a);
  20. appendToElement.appendChild(li);
  21. }
  22. };
  23. <strong>//减少重排版的一个方法是通过改变display 属性,临时从文档上移除<ul>元素然后再恢复它。</strong>
  24. var ul = document.getElementById(‘mylist‘);
  25. ul.style.display = ‘none‘;
  26. appendDataToElement(ul, data);
  27. ul.style.display = ‘block‘;
  28. <strong>//在文档之外创建并更新一个文档片断,然后将它附加在原始列表上。
  29. 文档片断是一个轻量级的document 对象,它被设计专用于更新、移动节点之类的任务</strong>
  30. var fragment = document.createDocumentFragment();
  31. appendDataToElement(fragment, data);
  32. document.getElementById(‘mylist‘).appendChild(fragment);
  33. <strong>//创建要更新节点的副本,然后在副本上操作,最后用新节点覆盖老节点</strong>
  34. var old = document.getElementById(‘mylist‘);
  35. var clone = old.cloneNode(true);
  36. appendDataToElement(clone, data);
  37. old.parentNode.replaceChild(clone, old);

推荐尽可能使用文档片断(第二种解决方案)因为它涉及最少数量的DOM 操作和重排版。唯一潜在的

缺点是,当前文档片断还没有得到充分利用,开发者可能不熟悉此技术。

(3)缓存布局信息

尽量减少对布局信息的查询次数,查询时将它赋给局部变量,并用局部变量参与计算。

Js代码  

  1. //timeout中的代码
  2. myElement.style.left = 1 + myElement.offsetLeft + ‘px‘;
  3. myElement.style.top = 1 + myElement.offsetTop + ‘px‘;
  4. if (myElement.offsetLeft >= 500) {
  5. stopAnimation();
  6. }
  7. //优化后
  8. current++
  9. myElement.style.left = current + ‘px‘;
  10. myElement.style.top = current + ‘px‘;
  11. if (current >= 500) {
  12. stopAnimation();
  13. }

六。动画中使用绝对坐标,使用拖放代理。

七。使用事件托管技术最小化事件句柄数量。

当页面中存在大量元素,而且每个元素有一个或多个事件句柄与之挂接(例如onclick)时,可能会影

响性能。连接每个句柄都是有代价的,无论其形式是加重了页面负担(更多的页面标记和JavaScript 代码)

还是表现在运行期的运行时间上。你需要访问和修改更多的DOM 节点,程序就会更慢,特别是因为事件

挂接过程都发生在onload(或DOMContentReady)事件中,对任何一个富交互网页来说那都是一个繁忙的

时间段。挂接事件占用了处理时间,另外,浏览器需要保存每个句柄的记录,占用更多内存。当这些工作

结束时,这些事件句柄中的相当一部分根本不需要(因为并不是100%的按钮或者链接都会被用户点到),

所以很多工作都是不必要的。

javascript之DOM优化,布布扣,bubuko.com

时间: 2024-11-03 03:39:36

javascript之DOM优化的相关文章

Javascript操作DOM常用API总结

Javascript操作DOM常用API总结 原文地址:http://luopq.com/2015/11/30/javascript-dom/ 类型 Node类型(ELEMENT_NODE:1 ATTRIBUTE_NODE:2 TEXT_NODE:3 COMMENT_NODE:8``DOCUMENT_NODE:9 DOCUMENT_FRAGMENT_NODE:11) 节点创建型(createElement createTextNode cloneNode createDocumentFragme

高性能Javascript(2) DOM编程

第三部分 DOM编程 文档对象模型(DOM)是一个独立于语言的,使用XML和HTML文档操作的应用程序接口(API).在浏览器中,主要与HTML文档打交道,在网页应用中检索XML文档也很常见.DOM APIs主要用于访问这些文档中的数据.尽管DOM是与语言无关的API,在浏览器中的接口却是以JavaScript实现的.客户端大多数脚本程序与文档打交道,DOM就成为JavaScript代码日常行为中重要的组成部分. 2.1 DOM Access and Modification  DOM访问和修改

【repost】Javascript操作DOM常用API总结

Javascript操作DOM常用API总结 文本整理了javascript操作DOM的一些常用的api,根据其作用整理成为创建,修改,查询等多种类型的api,主要用于复习基础知识,加深对原生js的认识. 基本概念 在讲解操作DOM的api之前,首先我们来复习一下一些基本概念,这些概念是掌握api的关键,必须理解它们. Node类型 DOM1级定义了一个Node接口,该接口由DOM中所有节点类型实现.这个Node接口在JS中是作为Node类型实现的.在IE9以下版本无法访问到这个类型,JS中所有

[转]JavaScript 的性能优化:加载和执行

原文链接:http://www.ibm.com/developerworks/cn/web/1308_caiys_jsload/index.html?ca=drs- JavaScript 的性能优化:加载和执行 蔡 愉晟, 软件工程师, IBM 简介: 随着 Web2.0 技术的不断推广,越来越多的应用使用 JavaScript 技术在客户端进行处理,从而使 JavaScript 在浏览器中的性能成为开发者所面临的最重要的可用性问题.而这个问题又因 JavaScript 的阻塞特性变的复杂,也就

javascript的性能优化tips

谈到javascript的性能优化,有好多点,比如把script放到离body闭合标签附近,合并多个script标签等等,还有一些代码的性能,for的性能不如while的性能好,用while模拟for循环等等等. 1.从加载开始 在浏览器中,js文件的执行和下载会阻塞css和dom的渲染,这是浏览器的单线程所致,后来chrome,ff等浏览器启用了js文件的并行下载,然而js文件的运行还是会被阻塞,有的浏览器支持defer关键字. <script type="text/javascript

【转】js JavaScript 的性能优化:加载和执行

JavaScript 的性能优化:加载和执行 转自:https://www.ibm.com/developerworks/cn/web/1308_caiys_jsload/ 随着 Web2.0 技术的不断推广,越来越多的应用使用 JavaScript 技术在客户端进行处理,从而使 JavaScript 在浏览器中的性能成为开发者所面临的最重要的可用性问题.而这个问题又因 JavaScript 的阻塞特性变的复杂,也就是说当浏览器在执行 JavaScript 代码时,不能同时做其他任何事情.本文详

让我们写快速的JavaScript,JS性能优化小窍门

JavaScript已经是目前最流行的语言了,它能做很多事情 - 网站界面,服务器端,游戏 ,操作系统 ,机器人 等等很多很多. 不过,说实话,即使它这么疯狂流行,它的性能还没有达到它的极限.是的,它在改进,但是等到它在各个方面赶上本地应用之前,在做一个HYBIRD混合应用时,你还不得不使用一些伎俩来优化它的性能. Firefox拥有目前最快的JavaScript解析器 SpiderMonkey, 有各种各样的让JavaScript的速度更快的努力,其中一个是asm.js. Asm.js是Jav

Javascript常见性能优化

俗话说,时间就是生命,时间就是金钱,时间就是一切,人人都不想把时间白白浪费,一个网站,最重要的就是体验,而网站好不好最直观的感受就是这个网站打开速度快不快,卡不卡. 当打开一个购物网站卡出翔,慢的要死,是不是如同心塞一样的感受,蓝瘦香菇,想买个心爱的宝贝都不能买,心里想这尼玛什么玩意. 那么如何让我们的网站给用户最佳的体验呢?大环境我们不说,什么网络啊,浏览器性能啊,这些我们无法改变,我们能改变的就是我们码农能创造的,那就是代码的性能.代码精简,执行速度快,嵌套层数少等等都是我们可以着手优化注意

JavaScript总结--DOM

对于Web前端开发,归根结底是三部分内容: 结构:HTML 表现:CSS 行为:JavaScript 在行为方面,主要是由JavaScript通过DOM对网页进行操作来实现的.DOM(Document Object Model),即文档对象模型,可以理解为一种接口. 用导图总结一下DOM涉及的内容. 这里,我们经常用的操作就是元素的获取,添加,如:getElementById,CreateElement,appendChild.不论是之后学的JQuery,还是Ajax,都要对网页进行操作,所以D