JavaScript操作DOM性能优化

铁汁是什么意思 2019-11-18 42 阅读

JavaScript主要功能之一就是用来操作DOM,但操作DOM是非常昂贵的行为。
在初学阶段,达成目标是主要目标,随着技术的进步,会自然而然的关注代码的性能。
代码的性能对于小型的项目影响不是太大,但是对于大型项目或者操作量较高的项目则有明显的影响。
下面介绍一下常见的提高性能的方式。
一.遍历元素集合:
应用中,可能需要使用指定方法获取元素对象集合,然后对其进行遍历。
代码实例如下:

<!DOCTYPE html>
<html>
<head>
<meta charset=" utf-8">
<meta name="author" content="http://www.cxvn.com/" />
<title>JavaScript操作DOM性能优化</title>
<style type="text/css">
#box li {
width: 350px;
height: 25px;
line-height: 25px;
font-size: 12px;
}
</style>
<script>
addEventListener("DOMContentLoaded",function(){
let lis=document.getElementsByTagName("li");
for(let index=0;index<lis.length;index++){
lis[index].style.color="blue";
}
},false);
</script>
</head>
<body>
<ul id="box">
<li>乐分享一</li>
<li>乐分享二</li>
<li>乐分享三</li>
<li>乐分享四</li>
<li>乐分享五</li>
<li>乐分享六</li>
</ul>
</body>
</html>

代码分析如下:
(1).通过getElementsByTagName方法获取li元素集合。
(2).此集合是动态的,也就是它能够自动实时感知li元素的增加或者减少。
(3).然后通过for循环遍历每一个li元素,再将其字体元素设置为蓝色。
上述代码并不是最优方式,由于集合是动态的,所以lis.length获取集合中的元素数量性能较差。
那么可以将元素集合的数量事先缓存起来,而不是每循环一次获取一次,代码修改如下:

<script>
addEventListener("DOMContentLoaded",function(){
let lis=document.getElementsByTagName("li");
let len=lis.length;
for(let index=0;index<len;index++){
lis[index].style.color="blue";
}
},false);
</script>

二.将多次样式操作合并为一次:
实际应用中,可能会使用如下方式设置元素的样式,代码片段如下:

<div>
let odiv = document.getElementById("ant");
odiv.style.color = "red";
odiv.style.background = "blue";
odiv.style.width = "200px";
odiv.style.height = "100px";
</div>

上述代码可以设置div元素的字体颜色、背景颜色和元素尺寸。
一切看起来很正常,但是性能比较低下,如果操作庞大,性能会有明显下降。
因为每一次使用style设置,都会引发页面的重绘或者重排,代码修改如下:
CSS代码如下:

<style type="text/css">
#ant {
background: blue;
color: red;
width:200px;
height: 200px;
}
</style>

JavaScript代码如下:

<script>
let odiv = document.getElementById("ant");
odiv.className = "ant";
</script>

使用上述代码,重绘和重排只有一次,可以极大提高想能。
三.经常需要重排的元素设置为绝对定位:
有些元素可能需要经常重排,那么可以将它们设置为绝对定位。
这样它们就可以脱离文档流,即便它们发生重排也不会影响其他元素,缩小了重排的范围。
四.使用fragment暂存节点:
假设我们需要依次创建若干个li元素,然后将其追加到ul中。
ul中追加li元素是一个重绘或者重排操作,很消耗性能,看如下代码片段:

<!DOCTYPE html>
<html>
<head>
<meta charset=" utf-8">
<meta name="author" content="http://www.cxvn.com/" />
<title>JavaScript操作DOM性能优化</title>
<script>
addEventListener("DOMContentLoaded",function(){
let arr=["乐分享一","乐分享二","乐分享三","乐分享四","乐分享五"];
let oul=document.getElementById("box");
for(let index=0;index<5;index++){
let li=document.createElement("li");
let oTxt=document.createTextNode("乐分享"+arr[index]);
li.appendChild(oTxt);
oul.appendChild(li);
}
},false);
</script>
</head>
<body>
<ul id="box"></ul>
</body>
</html>

上述代码通过for循环方式依次创建li元素,然后再依次将li元素追加到ul元素中。
虽然实现了预期效果,但是性能非常不好,因为进行了多次追加操作,进行了多次重绘重排。
所以可以将每一次附加操作暂存起来,然后一次性追加到ul中,进行一次重绘重排操作即可。
代码修改如下:

<!DOCTYPE html>
<html>
<head>
<meta charset=" utf-8">
<meta name="author" content="http://www.cxvn.com/" />
<title>JavaScript操作DOM性能优化</title>
<script>
addEventListener("DOMContentLoaded",function(){
let arr=["乐分享一","乐分享二","乐分享三","乐分享四","乐分享五"];
let oFragment=document.createDocumentFragment();
let oul=document.getElementById("box");
for(let index=0;index<5;index++){
let li=document.createElement("li");
let oTxt=document.createTextNode("乐分享"+arr[index]);
li.appendChild(oTxt);
oFragment.appendChild(li);
}
oul.appendChild(oFragment);
},false);
</script>
</head>
<body>
<ul id="box"></ul>
</body>
</html>

代码实现了相同的效果,但是性能更佳,分析如下:
(1).利用document.createDocumentFragment方法创建一个暂存器。
(2).然后将附加操作放入这个暂存器。
(3).最后将暂存器附加到ul中,事实就是将所有li元素一次性附加到ul。
五.巧用display:none元素:
隐藏元素不会影响不在渲染树中,对它的任何操作都不会引发重拍或者重绘操作。
所以要对元素进行比较复杂的各种操作时,如果允许的话,可以将其暂时隐藏起来。
操作完毕,再将其显示出来,这样只会产生一次重绘和重排操作。

最新游戏