jQuery EasyUI Datagrid性能優化專題(轉)

jQuery  EasyUI的Datagrid組件功能算是很強大了,不過性能確實不怎麼樂觀,而對於性能問題,網絡上幾乎也找不到相關的優化資料,所謂的牛人們可能 都望而卻步了。本博客之後會帶着分析Datagrid組件的性能問題,而且給出優化方案,也但願你們能集思廣益,給出一些好的想法。javascript

慢在哪些方面

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

  • 加載大數據量時比較慢(不考慮服務端返回數據的時間),這點尤爲體如今IE瀏覽器裏面;
  • 大數據量時,加載後,操做很不流暢,勾選慢,singleSelect爲true的話點選也比較慢,IE瀏覽器也是尤爲突出;
  • 數據量通常,可是字段特別多的話,加載和操做也比較慢,固然了,這種狀況比較少見;
  • 可編輯表格的性能則是更爲糟糕,數據量達到幾十條的時候,操做就會至關不流暢,IE依舊很突出

大數據量的加載

緣由分析

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

經過單步調試發現,默認視圖在最後將tr寫到table裏面用的是jQuery的html()函數,就是這個函數在IE下執行效率很是低。java

解決方案一:返璞歸真

jQuery是個很鋒利的工具,可有時候咱們也得返璞歸真一下,爲何非要用jQuery的html()函數呢,咱們就用javascript dom對象裏面的innerHtml屬性不就能夠了麼,並且換成innerHTML屬性方式的話,效率提升幾十倍。jquery

因此,大數據量加載慢的問題,就這麼簡單就解決了,修改默認視圖render方法最後那句:chrome

  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而已,我對這個視圖的源碼也分析過,請你們參照:dom

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

數據報表統計

如下是一些測試報表,測試環境請看報表標題(Y軸爲耗時,單位毫秒;X軸爲數據量):

勾選性能測試【IE9;jQuery-1.8.0;EasyUI-1.3.3;singleSelect:false】優化執行時間(ms)原版執行時間(ms)200條500條1000條2000條4000條6000條8000條10000條-1k0k1k2k3k4kHighcharts.com

能夠看出來,不管是在IE9下,勾選效率都提升了不少倍(chrome下效率也有顯著提升)。對於開啓singleSelect的優化思路是同樣的,因此不寫重複文字了。

渲染性能測試【IE9;不考慮服務器響應時間】優化渲染時間(ms)原版渲染時間(ms)200條500條1000條2000條4000條6000條8000條10000條-50k0k50k100k150k200k250kHighcharts.com

對於原版的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

相關文章
相關標籤/搜索