DOM效能小記

2022-03-09 08:57:45 字數 4521 閱讀 6250

在使用dom操作時,同樣的效果

用不同的方式來實現

,效能方面也會有很大的差異。尤其在移動式裝置上,資源本來就很有限,一旦dom寫不好的話操作就會非常卡頓。這個週末,就寫個dom效能小記吧。錯漏之處,望多指教。

1、淺說reflow

首先講講最近我才了解到的乙個比較深入且模糊的東西——reflow

從字面上理解的話,reflow有回流、重排的意思。它是指在dom內容更新或增刪時發生的乙個響應過程,可以理解為頁面內容改變了,然後發生重新排版這樣的乙個行為。

我們可以將執行dom操作細分為以下三個過程:讀取html內容——>頁面reflow——>展示更新內容。

由於reflow是乙個重整布局和樣式的過程,相當消耗效能。所以我們優化dom效能實際上就是避免執行更多dom操作,即減少reflow過程

2、減少reflow常用方法

採用臨時變數儲存,一次性操作dom

以我筆記本為例,分別測試了以下兩段**:

1

//**1

2 window.onload = function()7

}8//**2

9 window.onload = function

()15 oul.innerhtml =str;

16 }

t/ms

1

2

3

4

5

6

7

8

9

10

**1

9067.696

8900.826

9114.520

8987.592

9220.753

9344.496

8783.459

8797.731

9337.738

8835.503

**2

4.100

1.883

2.177

2.262

2.416

5.464

2.053

1.891

2.053

1.975

從上面資料明顯看得出,同樣執行10000次拼接,**二遠快於**一。

不難得出結論:減少dom訪問,改用外部變數臨時儲存內容,最後再一步執行dom操作的效率遠高於分次執行dom操作。

**二的速度約是**一的4000倍,可粗略計算出,innerhtml每查詢並賦值一次,用時就接近1ms。

採用class修改多個樣式,一次性更改屬性

分別測試以下**:

1

//**三

2 window.onload = function

()else18}

19}2021

//**四

22 window.onload = function

()else30}

31 }

同樣在chrome瀏覽器下測試執行用時如下,前五次為兩段**分開執行,後五次為兩段**放一起執行(排除電腦不同時間點執行的差異):

t/ms

1

2

3

4

5

6

7

8

9

10

**3

346.540

471.160

322.437

327.363

335.818

283.553

346.819

318.261

313.144

333.789

**4

38.666

20.042

19.550

26.465

27.294

38.429

33.793

37.031

34.928

36.221

從上面的資料可以看出,通過設定class改變多個樣式的方法比分次改變樣式明顯快得多。

在不考慮js**賦值運算增多帶來了誤差的情況下(實際上很小),**4的方法平均耗時也比**3的方法快10多倍。因為在**3中,我每改變乙個樣式都會產生一次reflow,即reflow了5次。而在**四中使用classname卻只reflow了一次,但一次reflow改變了多個樣式

這裡需要注意的是,不是所有樣式的改變都會產生reflow的。只有會影響布局的樣式才會,例如width,height,display,line-height,margin,padding,font,background等等。諸如color,opacity,visibility等則不會,因為它們只會產生repaint。你可以想象得到,改變顏色、透明度等值對頁面的結構是不會產生任何影響的。這裡我就不展開講了。

採用變數儲存節點屬性值,減少獲取次數

測試**:

1

//**5

2for (var i = 0; i < 10000; i++) else

8}910

//**6

11var u1 = document.getelementbyid('ul1');

12var uw =u1.offsetheight;

13for (var i = 0; i < 10000; i++) else

19 }

分別執行以上**10000次的10個時間樣本對比:  

t/ms

1

2

3

4

5

6

7

8

9

10

**5

1256.209

1175.189

1384.690

1241.207

1223.094

1371.524

1186.556

1176.889

1269.450

1215.922

**6

20.633

14.353

17.901

19.665

31.405

20.503

24.451

18.909

23.883

14.472

同樣可以看出,**6是明顯比**5執行速度快的。

當我們知道某乙個節點的某些屬性值是確定時,這時候我們可以將這個值儲存在變數中,而不需要每次重新獲取。否則當執行次數達到一定量後,會嚴重影響程式執行的速度。因為當第一次使用變數獲取某個節點的值時,頁面就會只reflow一次,並把這個值儲存在記憶體中。下次程式需要時從記憶體中取就可以了。而**5中則每次都沿著document去讀取這些值,這些值雖然沒有改變,但這些值是瀏覽器需要計算才能獲得的,所以每次都會reflow一次。

會導致reflow的屬性有offsetleft/top、offsetheight/width、scrolltop/left/width/height、clienttop/left/width/height等。

養成使用這種方法的

習慣,不但能提高程式效能,有時候還可以節省**量,使程式更簡潔。

JS 效能優化小記

js語法層面的效能優化 先看乙個2萬次的遍歷性能開銷圖 chrome 版本 83.0.4103.61 正式版本 64 位 發現了什麼?同樣是foreach 執行效率截然不同,所以不能簡單的對比 for for.of foreach 效能上的差異,理所當然的認為效能開銷所差無幾,建議使用for 迴圈 ...

如何寫出高效能DOM?

提高高效能dom就不得不提到回流和重繪,那麼什麼是回流什麼是重繪?回流 對於dom結構中的各個元素都有自己的盒子模型,這些都需要瀏覽器根據各種樣式 瀏覽器的 開發人員定義的 來計算並根據計算結果將元素放到它該出現的位置,這個過程稱為回流。重繪 當各種盒子的位置 大小以及其他屬性,例如顏色 字型大小等...

KDB和Oracle的效能pk小記

在偶然的機會聽到了kdb,然後帶著好奇和新鮮感體驗了一把這個傳說中和oracle 相似度達到99 的資料庫。其中一部分的驅動力在於這個活動的獎品很豐厚,參加活動後可以拿到乙個iwatch,確實是很划算的乙個活動。而對於kdb的認識,也是在對比調優中認識到的,其實結果還是大大超出我的預期。首先來簡單說...