高頻Dom操作,頁面性能優化(學習)

来源:http://www.cnblogs.com/zouxiaojia/archive/2017/09/10/7499926.html
-Advertisement-
Play Games

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樹的更改,會造成頁面的重排。瀏覽器佈局是從上到下的過程,修改當前元素不會對其前邊已經遍歷過的元素造成影響,但是如果在所有的節點前添加一個新的元素,則後續的所有元素都要進行重排。

  • 獲取某些屬性

    • 除了渲染樹的直接變化,當獲取一些屬性值時,瀏覽器為取得正確的值也會發生重排,這些屬性包括:offsetTopoffsetLeft、 offsetWidthoffsetHeightscrollTopscrollLeftscrollWidthscrollHeight、 clientTopclientLeftclientWidthclientHeightgetComputedStyle()

  • 瀏覽器視窗尺寸改變

    • 視窗尺寸的改變會影響整個網頁內元素的尺寸的改變,即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操作。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 上文我們講到了options的配置和獲取數據的方式,本文,我們繼續深入options的配置 一、html-webpack-plugin插件中的options除了自己定義了一些基本配置外,我們是可以任意的添加自定義的數據 webpack.dev.config.js文件: 我們在webpack.dev. ...
  • 一、概述 和select下拉列表相比,jquery+css實現的下拉列表具有更好的靈活性,第二部分的代碼為下拉列表的實現。 二、代碼 下拉列表效果如下: 下拉列表的選項為動態追加,使用on方法,採用事件委派機制,響應選項的單擊事件。 經過測試,以下代碼在Firefox 55.0和Safari 10. ...
  • 還記得我們上文中的index.html文件嗎? 那裡面的script標簽還是寫死的index.bundle.js文件,那麼怎麼把他們變成動態的index.html文件,這個動態生成的index.html文件會動態引入我們打包後生成的js文件呢?,我們可以使用插件html-webpack-plugin ...
  • 一、定義 用來描述或匹配一系列符合某個規則的字元串信息的字元串。 通常用來檢驗字元串是否符合某些規則,或者匹配(替換)被操作的字元串中的某些信息。 二、基本語法 1.以“/”開始,以另一個“/”結束 2.結束符“/”後可以有g(global-在整個字元串中搜索)、i(ignore-忽略大小寫)、m( ...
  • 本文繼續接著上文,繼續寫下webpack.config.js的其他配置用法. 一、把兩個文件打包成一個,entry怎麼配置? 在上文中的webpack.dev.config.js中,用數組配置entry webpack.dev.config.js文件代碼: 然後在src/js目錄下麵新建一個calc ...
  • 在標準流中,一個塊級元素在水平方向會自動伸展,直到包含它的元素的邊界;而在豎直方向和兄弟元素依次排列,不能併排。使用“浮動”方式後,塊級元素的表現就會有所不同。 CSS中有一個float屬性,預設為none,也就是標準流通常的情況。如果將float屬性的值設置為left或right,元素就會向其父元 ...
  • 本文由segementfalt上的一道instanceof題引出: var str = new String("hello world"); console.log(str instanceof String);//true console.log(String instanceof Functio ...
  • Angular Js 的初步認識和使用 一: 1.模塊化 定義模塊和控制器 ng-app="myapp" controller="myctrl" 指定模型 ng-model="" 獲取的屬性值: ng-bind="屬性名"或者{{屬性名}} 2.初始化模塊(在Script中進行) var myapp ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...