1. 程式人生 > >jQuery EasyUI Datagrid效能優化專題

jQuery EasyUI Datagrid效能優化專題

文章目錄

jQuery  EasyUI的Datagrid元件功能算是很強大了,不過效能確實不怎麼樂觀,而對於效能問題,網路上幾乎也找不到相關的優化資料,所謂的牛人們可能都望而卻步了。本部落格以後會帶著分析Datagrid元件的效能問題,並且給出優化方案,也希望大家能集思廣益,給出一些好的想法。

慢在哪些方面

以目前對Datagrid的瞭解程度去看待效能問題,主要有以下幾點:

  • 載入大資料量時比較慢(不考慮服務端返回資料的時間),這點尤其體現在IE瀏覽器裡面;
  • 大資料量時,載入後,操作很不流暢,勾選慢,singleSelect為true的話點選也比較慢,IE瀏覽器也是尤其突出;
  • 資料量一般,但是欄位特別多的話,載入和操作也比較慢,當然了,這種情況比較少見;
  • 可編輯表格的效能則是更為糟糕,資料量達到幾十條的時候,操作就會相當不流暢,IE依舊很突出

大資料量的載入

原因分析

不考慮服務端返回資料的時間,在前臺獲取到大資料量後,往表格裡插入tr的時候,IE執行的效率非常低,2000條資料要45秒左右,其他瀏覽器則很快。

通過單步除錯發現,預設檢視在最後將tr寫到table裡面用的是jQuery的html()函式,就是這個函式在IE下執行效率非常低。

解決方案一:返璞歸真

jQuery是個很鋒利的工具,可有時候我們也得返璞歸真一下,為什麼非要用jQuery的html()函式呢,我們就用javascript dom物件裡面的innerHtml屬性不就可以了麼,而且換成innerHTML屬性方式的話,效率提高几十倍。

所以,大資料量載入慢的問題,就這麼簡單就解決了,修改預設檢視render方法最後那句:

 
  1. //1.3.3版本是這樣的,其它版本也是這句程式碼
  2. $(_1e0).html(_1e4.join(""));

改為:

 
  1. $(_1e0)[0].innerHTML = _1e4.join("");

注意:innerHTML雖然符合w3c標準,而且各個瀏覽器也都支援,但是表現出的行為卻又差異,另類的瀏覽器依舊是IE,主要表現在以下幾個方面:

  • IE6,IE7,IE8瀏覽器設定innerHTML屬性會忽略html5屬性和標籤,搜尋關鍵詞"innerHTML IE html5";
  • IE幾乎所有版本設定innerHTML屬性時都會把href,src屬性自動轉化為絕對路徑,搜尋關鍵詞"innerHTML IE href";
  • IE幾乎所有版本的table相關標籤的innerHTML屬性是隻讀的(td除外),搜尋關鍵詞"innerHTML IE table;

幸運的是EasyUI的datagrid預設檢視沒有使用html5技術,呼叫innerHTML的節點也並非table節點(是div),而href,src等轉化為絕對路徑並沒有什麼影響。

解決方案二:使用scroll檢視

VirtualScrollView檢視官網已經寫出來了,不過有兩個Bug而已,我對這個檢視的原始碼也分析過,請大家參照:

http://www.easyui.info/archives/1404.html

勾選和點選

原因分析

勾選和點選(開啟singleSelect)慢的原因其實是一樣的,都是選擇器執行效率低,這裡我拿勾選的情況來分析。

具體的分析過程我就不描述了,知道用chrome,fireBug,IE開發者工具除錯的同學,應該都有定位問題的思路:先定位執行效率低的函式,再在函式內定位執行效率低的語句。

checkbox導致操作不流暢的原因,我最後定位到opts.finder.getTr這個方法上,我們來看它的程式碼片段:

 
  1. if (type == "checked") {
  2.     return (_21d == 1 ? dc.body1 : dc.body2).find(">table>tbody>tr.datagrid-row:has(div.datagrid-cell-check input:checked)");
  3. }

這段程式碼是獲取已經被勾選的rows,大家可以看到,這是純粹的jQuery選擇器查詢,效率就慢在has這個偽選擇器上,它是針對所有後代元素的,查詢的效率是比較慢的,又是在這麼多資料量的情況下,其效果就可想而知了。

優化方案一:選擇器優化

其實對於checkbox列的DOM結構是固定的,我們完全可以用速度快的選擇器來代替":has",我們先直接用路徑選擇器找到"input:checked",然後使用三次parent()函式返回tr,寫法雖然複雜了,但是效率應該提高一點,所以我們改成這樣:

 
  1. if (type == "checked") {
  2.     return (_21d == 1 ? dc.body1 : dc.body2).find(">table>tbody>tr.datagrid-row>td>div.datagrid-cell-check>input:checked").parent().parent().parent();
  3. }

我用自己的服務大概測試了修改前後的效率(jQuery版本1.8.0,EasyUI版本1.3.3,singleSelect為false,2000條資料勾選一條記錄的測試情況):

  瀏覽器 執行時間 瀏覽器 執行時間
原版 IE9 600ms chrome 60ms
選擇器優化 IE9 560ms chrome 60ms

從上面的結果可以看出,在這種測試條件下,我們提高的效率並不大,IE9下提高的效率儘管有所提高,但是還是很不理想,而chrome下效能基本一樣。測試過程中發現,如果使用jQuery2.0的話,IE9下的執行時間將達到45000ms,幾乎讓人奔潰,看來儘管IE9勉強支援jQuery2.x,但是效率很挫。

優化方案二:實時記錄優化法

既然慢在DOM結構巨大時,jQuery選擇器的搜尋效率不是很好(特別是在IE下)。如果我們每次操作都記錄下勾選的tr,那麼就完全可以繞開選擇器。

具體該怎麼做呢,我們給$.data(target,'datagrid')變數增加兩個屬性:"checkedTrsBody1"和"checkedTrsBody2"分別儲存frozen部分和normal部分被勾選tr的引用,然後在各個設計到勾選的操作中維護這兩個屬性。最後,獲取被勾選tr的時候就可以直接從這兩個屬性中取了,其耗時是可以忽略的。

那麼究竟哪些操作會影響到被勾選的tr呢,我們羅列一下,也就以下幾種:"checkRow","uncheckRow","uncheckAll","checkAll","deleteRow","loadData","load","reload".我們只要在這些介面中維護起"checkedTrsBody1"和"checkedTrsBody2"屬性就可以了。

至於具體的程式碼怎麼改,我就不貼了,最好就直接改動原始碼了,思路很清晰,請各位自己去實現,是在理不出頭緒的,請參照我的實現:

http://www.easyui.info/version/jquery-easyui-1.3.3/plugins/jquery.datagrid.js

資料報表統計

勾選效能測試【IE9;jQuery-1.8.0;EasyUI-1.3.3;singleSelect:false】

  優化執行時間(ms) 原版執行時間(ms)
200條 7 64
500條 20 160
1000條 27 308
2000條 53 623
4000條 107 1323
6000條 192 2072
8000條 265 2865
10000條 331 3611

可以看出來,無論是在IE9下,勾選效率都提高了很多倍(chrome下效率也有顯著提高)。開啟singleSelect的優化思路是一樣的,所以不寫重複文字了。

渲染效能測試【IE9;不考慮伺服器響應時間】:

  優化渲染時間(ms) 原版渲染時間(ms)
200條 49 326
500條 122 1821
1000條 253 7002
2000條 525 27320
4000條 1083 110115
6000條 1683 200000
8000條 2261 200000
10000條 2900 200000

原版的datagrig,我本地的測試環境資料在4000條以上時,IE9基本就卡死了(可能機器效能不太好),無統計價值了,即便是4000條資料,也要將近2分鐘才渲染完,顯然沒人能夠忍受。

從報表很明顯可以看出優化過的表格,即便是10000條資料,3秒也就渲染完成了。

優化演示

未優化版本:http://www.easyui.info/version/jquery-easyui-1.3.3/demo/datagrid/bigdata_checkbox.html

優化版本:http://www.easyui.info/version/jquery-easyui-1.3.3/demo/datagrid/bigdata_checkbox_optimized.html

  *******轉載:http://www.easyui.info/archives/1435.html