1.1 DOM操作對頁面的影響 通過js操作DOM的代價很高,影響頁面性能的主要問題有如下幾點: 訪問和修改DOM元素 修改DOM元素的樣式,導致重繪或重排 通過對DOM元素的事件處理,完成與用戶的交互功能 訪問和修改DOM元素 修改DOM元素的樣式,導致重繪或重排 通過對DOM元素的事件處理,完成 ...
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 }View Code
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 }View Code
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();View Code
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";View Code
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 })View Code
在未優化代碼中,每對element進行一次樣式更改都會影響該元素的集合結構,最糟糕情況下會觸發三次重排。優化方式:利用js或jquery對該元素的class重新賦值,獲得新的樣式,這樣減少了多次的DOM操作。