前言
在前端開發的過程中,javascript極爲重要的一個功能就是對DOM對象的操作,無論增刪改查在前端頁面操作這一範圍內都是比較消耗性能的.如何高效率的,便捷的操作DOM,這就是本文要講述的.希望看完全文,你能知道如何更高效的通過原生js以及jQuery操作DOM元素.
操作DOM
這裏我希望介紹的相對系統一點,而不是東一句西一句,所以把Javascript和jQuery常用操作DOM的內容歸納成思維導圖方便閱讀.這裏就總結出最基本最常用的DOM操作.
Javascript:
jQuery:
上面的思維導圖分別是javascript和jQuery下操作DOM的一些常用Function,並不完全我僅僅列出相對常用的.這裏我比較推薦的是jQuery的操作方式,更加便捷的同時在性能上也相對有所保障.
性能影響
DOM操作會導致最重要的,也是我們最需要的問題就是導致用戶阻塞的重構(reflow)和重繪(repaint).比較通俗的一句話就是你在頁面上的任何操作都是有代價的,有些大有些小,如果我們的操作比較頻繁或者波及範圍較大,那麼就要講究方式和技巧.reflow和repaint就是我們在改變頁面或者說操作DOM時,會帶來的兩種後果.
reflow意味着結構的改變,比如一堆元素堆疊,改變其中一個的寬高,那麼相應的所有元素的位置都要改變.repaint意味着樣式的改變比如div調整了背景色等,但是位置不變,只改變我們操作的元素.所以通常來看repaint的代價要遠小於reflow,速度也更快.
影響性能的因素我們已經知道了,那麼下面看一下怎麼避免.
更有效的操作
最重要的觀點:既然任何DOM操作都有代價,那麼最好就是不操作或者最少的操作DOM.所以首先記住一個原則,將DOM操作儘量少!這裏有我認爲主要的4個原則,記下來足以應付大多數情況.
(1) 能放到DOM操作之外的操作就放到外面,DOM操作要儘量少.
DOM操作優化中這一觀點在網上已經很普及了,很多例子都有比如遍歷一個數組然後逐漸把內容添加到DOM上,這裏就推薦先遍歷完數組,然後一次性在DOM上操作.大家可以看代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
//
不好的做法 for
( var
i=0; i < items.length; i++){ var
item = document.createElement( "li" ); item.appendChild(document.createTextNode( "Option
"
+ i); list.appendChild(item); }
//
更好的做法 //
使用容器存放臨時變更, 最後再一次性更新DOM var
fragment = document.createDocumentFragment(); for
( var
i=0; i < items.length; i++){ var
item = document.createElement( "li" ); item.appendChild(document.createTextNode( "Option
"
+ i); fragment.appendChild(item); } list.appendChild(fragment); |
(2) 大範圍操作先把容器隱藏,在其中操作完成後,再顯示.
這是一個我剛接觸前端時遇到的一個優化辦法,當時很不理解爲什麼display=none之後操作就算是性能優化了.但是數據證明如此渲染確實快了很多,這個的原理要涉及到瀏覽器加載和渲染的原理,簡單說就是隱藏的元素其中不會產生reflow.這個例子我就不寫了,很簡單.
(3) 樣式操作不要注意修改屬性,直接替換class
這個還是比較容易理解的,你逐一修改要訪問很多次,而替換class就相當於批量操作了,訪問一次DOM就可以了,當然性能提高了.
(4) 用變量保存DOM對象而不是多次獲取,同時減少操作DOM屬性的次數.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
//不好 function
addAnchor(parentElement, anchorText, anchorClass) { var
element = document.createElement( 'a' ); parentElement.appendChild(element); element.innerHTML
= anchorText; element.className
= anchorClass; } //更好 function
addAnchor(parentElement, anchorText, anchorClass) { var
element = document.createElement( 'a' ); element.innerHTML
= anchorText; element.className
= anchorClass; parentElement.appendChild(element); } |
總結
說到這裏DOM的操作就差不多了,其實沒有什麼太新鮮的內容只是做了一個系統點總結.對於性能這部分要平時積累這個意識,因爲大多數時候它在開發過程中體現的並不明顯.本文還有很多不足,希望大家留言溝通吧.