写在前面
总所周知,在前端的日常里面,采用JS操作DOM节点的情况占据了大多数。虽然现在有MVVM主流框架代替我们做了这些事情,但充分理解在DOM操作各种损耗问题,将有助于让我们更加理解和优化问题。
DOM简介
DOM,全称文档对象模型。是一个独立于语言的,用于操作XML和HTML文档的程序接口。在浏览器中,主要用来与HTML文档打交道,同样也用在Web程序上获取XML文档上,并使用DOM API用来访问文档中的数据。
但是浏览器中通常会把DOM和JavaScript独立实现。所以这两个独立的功能只要通过接口彼此连接,就会产生消耗。如果分别把DOM和JavaScript想象成孤岛,那么js每次访问DOM都需要消耗资源。访问DOM的次数越多,费用也就越高。因此,推荐的做法就是尽可能减少访问的次数。
DOM访问和操作的优化方式
避免HTML元素集合的循环操作
举个例子,编写一个函数用来修改元素文本内容。
function innerHTMLLoop(){
for(var count = 0;count < 15000;count++){
// 错误方式
document.getElementById('here').innerHTML += 'a'
}
}
该方法的问题是在每次循环时都引用innerHTML属性值,正确的做法讲需要插入的文本用一个局部变量缓存起来,再一次性插入innerHTML属性。如下:
function innerHTMLLoop2(){
var content = ''
for(var count = 0;i < 15000;count++){
content += 'a'
}
document.getElementById('here').innerHTML = content
}
节点克隆比单纯使用创建createElement稍快
使用DOM方法更新内容的方法除了createElement之外,还可以辅助使用element.cloneNode方法替代掉createElement。
比如,我想要动态拼凑成一个表格,常规的方法肯定是在每次循环里面依次使用createElement创建节点之后,再把自己的子元素append起来。使用cloneNode之后其实大方向上不变,就是先初始化创建好各个节点,然后在循环体里替换掉createElement。
function tableCloneDOM(){
var i , table, thead, tbody, tr, th ,a , ul ,li,
oth = document.createElement('th'),
otr = document.createElement('tr'),
oa = document.createElement('a'),
oli = document.createElement('li') ,
oul = document.createElement('ul');
tbody = document.createElement('tbody');
for(var i = 1;i <= 1000;i++){
tr = otr.cloneNode(false)
td = otd.cloneNode(false)
// 循环其他部分
}
// 生成表格
document.getElementById('here').append(table)
}