1.1 DOM操作对页面的影响
通过js操作DOM的代价很高,影响页面性能的主要问题有如下几点:
- 访问和修改DOM元素
- 修改DOM元素的样式,导致
重绘
或重排
- 通过对DOM元素的事件处理,完成与用户的交互功能
DOM的修改会导致重绘
和重排
。
- 重绘是指一些样式的修改,元素的位置和大小都没有改变;
- 重排是指元素的位置或尺寸发生了变化,浏览器需要重新计算渲染树,而新的渲染树建立后,浏览器会重新绘制受影响的元素。
页面重绘的速度要比页面重排的速度快,在页面交互中要尽量避免页面的重排操作。浏览器不会在js执行的时候更新DOM,而是会把这些DOM操作存放在一个队列中,在js执行完之后按顺序一次性执行完毕,因此在js执行过程中用户一直在被阻塞。
2.1 导致页面重排的一些操作:
- 内容改变
- 文本改变或图片尺寸改变
- DOM元素的几何属性的变化
- 例如改变DOM元素的宽高值时,原渲染树中的相关节点会失效,浏览器会根据变化后的DOM重新排建渲染树中的相关节点。如果父节点的几何属性变化时,还会使其子节点及后续兄弟节点重新计算位置等,造成一系列的重排。
- DOM树的结构变化
- 添加DOM节点、修改DOM节点位置及删除某个节点都是对DOM树的更改,会造成页面的重排。浏览器布局是从上到下的过程,修改当前元素不会对其前边已经遍历过的元素造成影响,但是如果在所有的节点前添加一个新的元素,则后续的所有元素都要进行重排。
- 获取某些属性
- 除了渲染树的直接变化,当获取一些属性值时,浏览器为取得正确的值也会发生重排,这些属性包括:
offsetTop
、offsetLeft
、offsetWidth
、offsetHeight
、scrollTop
、scrollLeft
、scrollWidth
、scrollHeight
、clientTop
、clientLeft
、clientWidth
、clientHeight
、getComputedStyle()
。 - 浏览器窗口尺寸改变
- 窗口尺寸的改变会影响整个网页内元素的尺寸的改变,即DOM元素的集合属性变化,因此会造成重排。
2.2 导致页面重绘的操作
- 应用新的样式或者修改任何影响元素外观的属性
- 只改变了元素的样式,并未改变元素大小、位置,此时只涉及到重绘操作。
- 重排一定会导致重绘
- 一个元素的重排一定会影响到渲染树的变化,因此也一定会涉及到页面的重绘。
3. 针对操作DOM的性能优化方法总结
为了减少DOM操作对页面性能产生的影响,在实现页面的交互效果时一定要注意一下几点:
1.减少在循环内进行DOM操作,在循环外部进行DOM缓存
1 //优化前代码 2 function Loop() { 3 console.time("loop1"); 4 for (var count = 0; count < 15000; count++) { 5 document.getElementById(‘text‘).innerHTML += ‘dom‘; 6 } 7 console.timeEnd("loop1"); 8 }
1 //优化后代码 2 function Loop2() { 3 console.time("loop2"); 4 var content = ‘‘; 5 for (var count = 0; count < 15000; count++) { 6 content += ‘dom‘; 7 } 8 document.getElementById(‘text2‘).innerHTML += content; 9 console.timeEnd("loop2"); 10 }
2.只控制DOM节点的显示或隐藏,而不是直接去改变DOM结构
3.操作DOM前,先把DOM节点删除或隐藏
1 var list1 = $(".list1"); 2 list1.hide(); 3 for (var i = 0; i < 15000; i++) { 4 var item = document.createElement("li"); 5 item.append(document.createTextNode(‘0‘)); 6 list1.append(item); 7 } 8 list1.show();
display属性值为none的元素不在渲染树中,因此对隐藏的元素操作不会引发其他元素的重排。如果要对一个元素进行多次DOM操作,可以先将其隐藏,操作完成后再显示。这样只在隐藏和显示时触发2次重排,而不会是在每次进行操作时都出发一次重排。
4.最小化重绘和重排
1 //优化前代码 2 var element = document.getElementById(‘mydiv‘); 3 element.style.height = "100px"; 4 element.style.borderLeft = "1px"; 5 element.style.padding = "20px";
1 //优化后代码 2 //js操作 3 .newStyle { 4 height: 100px; 5 border-left: 1px; 6 padding: 20px; 7 } 8 element.className = "newStyle"; 9 //jquery操作 10 $(element).css({ 11 height: 100px; 12 border-left: 1px; 13 padding: 20px; 14 })
在未优化代码中,每对element进行一次样式更改都会影响该元素的集合结构,最糟糕情况下会触发三次重排。优化方式:利用js或jquery对该元素的class重新赋值,获得新的样式,这样减少了多次的DOM操作。
时间: 2024-12-31 03:57:20