DOM:文档对象模型,是一个独立于语言的,用来操作XML和HTML文档的程序接口(API)。
浏览器通常会把DOM和javascript独立实现,每次连接DOM和ECMAScript,都会被收取“过桥费”(性能消耗)。
优化方法:
1.减少访问DOM的次数,把运算尽量留在ECMAScript这一端处理。
慢:
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;
}
2.如果需要多次访问某个DOM节点,请使用局部变量存储它的引用。
3.innerHTML属性和类似 document.createElement的原生DOM方法比较:在除开最新版的Webkit内核(Chrome和Safari)之外的所有浏览器中,innerHTML会更快一些。
4.节点克隆:使用element.cloneNode()先创建需要重复的元素,然后重复拷贝操作,但改善不是很明显。
5.小心处理HTML集合,它实时连系着底层文档。把集合的长度缓存到一个变量中,并在迭代中使用它。如果需要经常操作集合,建议把它拷贝到一个数组中。
HTML集合是包含了DOM节点引用的类数组对象,并不是真正的数组(没有push(),slice()等方法),但是有length属性也能以数字索引的方式访问列表元素。
如:document.getElementsByTagName()等
把集合的长度缓存到一个变量中,并在迭代中使用它。
function loopCacheLengthCollection() {
var coll = document.getElementsByTagName(‘div');
var len = coll.length;
for (var i=0;i<len;i++) {
/*代码处理*/
}
}
当遍历一个集合时,第一优先原则是把集合存储在局部变量中,并把length缓存在循环外部,然后,使用局部变量替代这些需要多次读取的元素。
function collectionNodesLocal() {
var coll = document.getElementsByTagName(‘div’),
len = coll.length,
name = ‘',
el = null;
for (var i=0;i<len;i++) {
el = coll[i];
name = el.nodeName;
name = el.nodeType;
name = el.tagName;
}
return name;
}
6.如果可以的话,选择速度更快的API。
某些情况下,需要只访问元素节点:
属性名 被替代的属性
children childNodes
childElementCount childNodes.length
firstElementChild firstChild
lastElementChild lastChild
nextElementSibling nextSibling
previousElementSibling previousSibling
注:IE6,7,8只支持children属性。children属性不包含空白节点。
使用选择器API,如:querySelectorAll() 和querySelector()
注:IE8,Firefox3.5,Safari3.1,Chrome1,Opera10以上支持。
7.留意重绘和重排,批量修改样式时,“离线”操作DOM树,使用缓存,并减少访问布局信息的次数。
重排(reflow):当DOM的变化影响了元素的几何属性(宽、高),浏览器需要重新计算元素的几何属性,同样其它元素的几何属性也会受到影响,浏览器会使渲染树中受影响的部分失效,并重新构造渲染树。
重绘(repaint):完成重排后,浏览器会重新绘制受影响的部分到屏幕中。
减少重绘、重排次数:
合并所有修改,然后一次处理掉(cssText属性、修改CSS的class名称);
使元素脱离文档流-对其应用多重改变-把元素带回文档流中(display属性、文档片段document.createDocumentFragment()-推荐、为需要的节点创建备份,对副本进行操作);
动画中使用绝对定位;
8.使用事件委托来减少事件处理器的数量。