`

javascript之DOM优化

阅读更多

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

 

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

 

function innerHTMLLoop() {
for (var count = 0; count < 15000; count++) {
document.getElementById('here').innerHTML += 'a';
}
}
function innerHTMLLoop2() {
var content = '';
for (var count = 0; count < 15000; count++) {
content += 'a';
}
document.getElementById('here').innerHTML += content;
}

 innerHTMLLoop2显然要比innerHTMLLoop更好。

 

 

 

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

(此点结合第三点一起)

 

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

 

HTML集合有:
document.getElementsByName()
document.getElementsByClassName()
document.getElementsByTagName_r()
document.images
document.links
document.forms
document.forms[0].elements

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

 

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

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

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

 

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

 

 

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

 

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

 

 

 

var coll = document.getElementsByTagName_r('div');
var ar = toArray(coll);
//slower
function loopCollection() {
for (var count = 0; count < coll.length; count++) {
}
}
// faster
function loopCopiedArray() {
for (var count = 0; count < arr.length; count++) {
}
}
// faster
function loopCacheLengthCollection() {
var coll = document.getElementsByTagName_r('div'),
len = coll.length;
for (var count = 0; count < len; count++) {
}
}

 

 

 

 

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

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

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

 

// slow
function collectionGlobal() {
var coll = document.getElementsByTagName_r('div'),
len = coll.length,
name = '';
for (var count = 0; count < len; count++) {
name = document.getElementsByTagName_r('div')[count].nodeName;
name = document.getElementsByTagName_r('div')[count].nodeType;
name = document.getElementsByTagName_r('div')[count].tagName;
}
return name;
};
// faster
function collectionLocal() {
var coll = document.getElementsByTagName_r('div'),
len = coll.length,
name = '';
for (var count = 0; count < len; count++) {
name = coll[count].nodeName;
name = coll[count].nodeType;
name = coll[count].tagName;
}
return name;
// fastest
function collectionNodesLocal() {
var coll = document.getElementsByTagName_r('div'),
len = coll.length,
name = '',
el = null;
for (var count = 0; count < len; count++) {
el = coll[count];
name = el.nodeName;
name = el.nodeType;
name = el.tagName;
}
return name;
};

 

 

 

四。可能的话,使用速度更快的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 和风格改变合并到一个批次中一次性执行。

 

 

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

//better
var el = document.getElementById('mydiv');
el.style.cssText = 'border-left: 1px; border-right: 2px; padding: 5px;';

如果你打算保持当前的风格,你可以将它附加在cssText 字符串的后面。
el.style.cssText += '; border-left: 1px;';

//or
var el = document.getElementById('mydiv');
el.className = 'active';

 

 

(2)离线操作DOM

 

var data = [
{
"name": "Nicholas",
"url": "http://nczonline.net"
},
{
"name": "Ross",
"url": "http://techfoolery.com"
}
];
//一个通用的函数,用于将新数据更新到指定节点中
function appendDataToElement(appendToElement, data) {
var a, li;
for (var i = 0, max = data.length; i < max; i++) {
a = document.createElement('a');
a.href = data[i].url;
a.appendChild(document.createTextNode(data[i].name));
li = document.createElement('li');
li.appendChild(a);
appendToElement.appendChild(li);
}
};

//减少重排版的一个方法是通过改变display 属性,临时从文档上移除<ul>元素然后再恢复它。
var ul = document.getElementById('mylist');
ul.style.display = 'none';
appendDataToElement(ul, data);
ul.style.display = 'block';

//在文档之外创建并更新一个文档片断,然后将它附加在原始列表上。
文档片断是一个轻量级的document 对象,它被设计专用于更新、移动节点之类的任务
var fragment = document.createDocumentFragment();
appendDataToElement(fragment, data);
document.getElementById('mylist').appendChild(fragment);

//创建要更新节点的副本,然后在副本上操作,最后用新节点覆盖老节点
var old = document.getElementById('mylist');
var clone = old.cloneNode(true);
appendDataToElement(clone, data);
old.parentNode.replaceChild(clone, old);

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

 

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

 

(3)缓存布局信息

 

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

 

//timeout中的代码
myElement.style.left = 1 + myElement.offsetLeft + 'px';
myElement.style.top = 1 + myElement.offsetTop + 'px';
if (myElement.offsetLeft >= 500) {
stopAnimation();
}

//优化后
current++
myElement.style.left = current + 'px';
myElement.style.top = current + 'px';
if (current >= 500) {
stopAnimation();
}

 

 

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

 

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

 

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

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

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

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

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

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

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

 

 

 

分享到:
评论
1 楼 随风逐云 2015-04-16  
var alldivs = document.getElementsByTagName_r('div'); 
for (var i = 0; i < alldivs.length; i++) { 
document.body.appendChild(document.createElement('div')) 
}
alldivs.length会随时更新的吗 循环部分并不包含 alldivs的赋值啊

相关推荐

    JavaScript.DOM编程艺术(第2版)附录及源码.rar

    9. **DOM性能优化**:理解DOM操作的性能影响,如避免不必要的重绘和回流,使用文档碎片等技巧,能够提升网页性能。 10. **附录内容**:可能包含常见问题解答、API参考、术语表等,有助于读者巩固所学知识。 通过...

    JavaScript DOM编程艺术【第2版&高清】.pdf

    例如,DocumentFragment的使用、DOM优化技巧、跨浏览器兼容性处理等。 上述知识点构成了《JavaScript DOM编程艺术》一书的核心内容。通过系统学习这些知识,读者可以掌握使用JavaScript进行DOM操作的基本理论和实践...

    JavaScript & DOM Enlightenment

    JavaScript和DOM Enlightenment是关于Web开发中的核心技术的深入学习资源,主要涵盖了JavaScript编程语言以及文档对象模型(Document Object Model)的应用。这两个概念对于任何希望成为前端开发者的人来说都是至关...

    javascriptDom编程艺术+源码

    此外,书中还涉及了一些高级话题,如异步编程(AJAX)、DOM遍历优化和性能考虑,以及如何避免常见的JavaScript和DOM相关的陷阱。这些章节有助于读者在实践中提高代码质量和效率,为开发高性能的Web应用做好准备。 ...

    JavaScript+DOM编程艺术

    《JavaScript+DOM编程艺术》是一本深入探讨JavaScript与DOM(Document Object Model)结合使用的经典教程。这本书旨在为读者提供JavaScript语言基础以及DOM操作的核心技能,同时强调了在前端Web开发中至关重要的设计...

    [JavaScript.DOM编程艺术(第2版)-高清扫描

    8. 最佳实践和性能优化:提供关于编写高效、可维护JavaScript代码的建议,以及如何优化DOM操作以提升页面性能。 通过对这本书的学习,读者将掌握JavaScript与DOM的结合使用,能够开发出更加动态和交互性的Web应用。...

    JavaScript+DOM编程艺术(最新中文版)

    最后,书中可能还会讨论一些高级话题,如闭包、作用域、原型链,这些是JavaScript的高级特性,对于深入理解和优化代码有着重要作用。同时,现代JavaScript的新特性,如箭头函数、Promise、模板字符串等也可能有所...

    JavaScriptDOM编程艺术

    12. **DOM性能优化**:了解DOM操作可能带来的性能影响,比如避免不必要的DOM遍历,使用文档片段批量操作,以及利用事件委托等技术提高效率。 通过学习《JavaScript DOM编程艺术》,读者将掌握如何利用JavaScript与...

    [JavaScript.DOM高级程序设计](加)桑贝斯.扫描版

    性能优化也是高级JavaScript DOM编程的一部分,如批量操作DOM以减少重绘和回流,或者使用MutationObserver监听DOM变化,避免不必要的循环检测。 最后,随着Web应用复杂性的增加,模块化和组织代码的方式也变得尤为...

    JavaScript+DOM编程艺术(扫描版含源代码)

    6. **DOM高级技巧**:涵盖动画效果、DOM遍历和优化策略。 源代码的提供让读者有机会亲自实践书中示例,从而更深刻地理解JavaScript和DOM的结合使用,提升网页动态编程技能。通过这本书,无论是初学者还是有一定经验...

    记录我的旅程之JavaScript Dom系列里面的所有例题

    总的来说,这个“记录我的旅程之JavaScript DOM系列”涵盖了DOM操作的各个方面,包括元素的查找、创建、修改、删除、事件处理、动画和性能优化。通过实践这些例题,你将能更熟练地驾驭JavaScript与DOM的交互,提升...

    javascript 操作DOM

    JavaScript操作DOM(Document Object Model)是网页开发中的核心技能之一,它允许我们动态地修改、添加和删除HTML或XML文档的结构与内容。DOM是一种树形结构,将页面元素视为对象,提供了丰富的接口来实现对这些对象...

    DOM Scripting.Web.Design.with.JavaScript.and.the.Document.Object.Model(JavaScript DOM编程艺术)

    《DOM Scripting: Web Design with JavaScript and the Document Object Model》是由Jeremy Keith撰写的一本关于JavaScript和DOM编程的经典著作。这本书深入浅出地介绍了如何利用JavaScript动态操控网页内容,提升...

    JavaScript DOM编程艺术 第2版 及源码

    8. **DOM性能优化**:书中还会探讨如何避免DOM操作导致的性能问题,如批量操作、延迟加载和使用文档碎片等最佳实践。 9. **源码分析**:提供的源码文件可能包含书中示例的实现,读者可以通过阅读源码加深对概念的...

    JavaScript DOM编程艺术(第2版).pdf

    此外,书中还会探讨性能优化策略,如减少DOM操作,利用缓存,以及使用requestAnimationFrame优化动画性能。这些知识对于编写高性能的前端应用至关重要。 总之,《JavaScript DOM编程艺术(第2版)》是一本全面而...

    JavaScriptDOM编程艺术第二版

    7. **DOM性能优化**:理解DOM操作对页面性能的影响,学习最佳实践以提高页面加载和交互速度。 8. **DOM库和框架**:虽然本书可能主要讲解基础,但也会提及jQuery等DOM库,它们简化了DOM操作并提供了一致的API。 ...

    javascriptDOM

    10. **性能优化**:理解DOM操作可能会引起重绘和回流,了解如何最小化这些操作对性能的影响,比如批量修改DOM、使用`createDocumentFragment()`等。 在JavaScript和CSS的学习中,两者是相互关联的。CSS用于定义网页...

Global site tag (gtag.js) - Google Analytics