提升web應用程序的性能- 找出瓶頸,加快客戶端內容的速度

簡介: 作為 web 用戶,我們知道頁面加載或刷新的速度對其成功至關重要。本文將幫助您更好地理解影響 web 應用程序性能的因素。學習識別這些問題並且找到客戶端內容的瓶頸。探索 JavaScript、DOM、CSS 和 Dojo 小部件的性能問題。將通過一個例子展示使用 YSlow 和 Firebug 適當調整 Dojo 小部件。
本文的標簽:  ajax, dhtml_(dynamic_html), ecmascript, javascript, web, 應用程序的性能, 應用集成, 技巧, 提升
概覽
Rich Internet applications (RIAs) 在 Web 2.0 領域非常流行。為瞭提供新鮮、別致的用戶體驗,很多網站用 JavaScript 或 Flash 將復雜的內容從後臺服務器搬到前臺客戶端。如果 數據較少的話,這提供瞭一個方便、新穎,流暢的用戶界面(UI)。如果要將大量內容從服務器轉移到客戶端並在瀏覽器呈現,性能將顯著下降。挑戰是找到瓶頸,確定解決方案。
在瀏覽器中調整性能問題比在 Java 應用程序中更難。開發人員在各種瀏覽器中調試 JavaScript 的方法要少得多。在 Mozilla Firefox 中,可以使用 Firebug 調試 JavaScript,但仍然不能調整很多性能問題,如瀏覽器呈現消耗時間。為瞭解決這些問題,有必要開發瀏覽器插件來監控時間響應,以及確定其他對應解 決方案如部分呈現或延時加載。
學習診斷 web 應用程序中的性能問題,找到客戶端內容中的瓶頸,並調整性能。
JavaScript 和 HTML DOM
JavaScript 是用在 Internet 上的最流行的腳本語言。數以萬計的 web 頁面設計師使用 JavaScript 來改善設計、驗證表單、檢查瀏覽器以及創建 cookie。HTML Document Object Model (DOM) 定義瞭訪問和操作 HTML 文檔的標準方法。它將 HTML 文檔表示成節點樹,其中包含元素、屬性和文本內容。
通過使用 HTML DOM,JavaScript 能訪問 HTML 文檔中所有節點並操作它們。很多主流瀏覽器都支持 JavaScript 和 HTML DOM,而且很多網站也使用它們。它們使用的性能顯著影響到整個 RIAs 的性能。
JavaScript 性能和函數
在 JavaScript 中,當需要某一功能時,使用 函數。盡管有些情形下可以用字符串代替函數,我們還是建議您盡可能使用函數。在 JavaScript 中,函數在使用前會預編譯。
例如,看 清單 1 中的 eval 方法。
清單 1. eval 方法用字符串作參數
function square(input) {
  var output;
  eval('output=(input * input)');
  return output;
}
eval 方法計算平方值並輸出結果,但性能不好。此例使用字符串 output=(input*input) 作為 eval 方法的參數,無法利用 JavaScript 預編譯。
清單 2 顯示瞭一個完成此任務的更好的方法。
清單 2. 使用函數作參數的 Eval 方法
function square(input) {
  var output;
  eval(new function() { output=(input * input)});
  return output;
}
使用函數代替字符串作參數確保新方法中的代碼能被 JavaScript 編譯器優化。
函數作用域
JavaScript 函數作用域鏈中的每個作用域都包含幾個變量。理解作用域鏈很重要,這樣才能利用它。清單 3 顯示的是一個函數作用域樣例。
清單 3. 函數作用域
function test() {
  var localVar = “test”;
  test1(this. localVar);
var pageName = document.getElementById(“pageName”);
}
圖 1 顯示瞭作用域鏈結構。

圖 1. 作用域鏈結構

理解作用域鏈的結構對利用它很重要

使用局部變量比使用全局變量快得多,因為在作用域鏈中越遠,解析越慢。
如果代碼中有 with 或 try-catch 語句,作用域鏈會更復雜。圖 2 顯示的是 try-catch 語句的作用域鏈。
圖 2. Try-catch 作用域鏈結構

作用域鏈中的 try-catch 語句使其更加復雜

字符串函數
JavaScript 中最不可取的函數是字符串連接。我通常使用 + 號來實現連接。清單 4 顯示瞭一個此類樣例。
清單 4. 字符串連接
var txt = “hello” + “ ” + “world”;
這條語句創建瞭幾個包含連接結果的中間字符串。這樣在後臺連續創建和銷毀字符串導致極低的字符串連接性能。早期的瀏覽器對這樣的操作沒有優化。我們建議您創建一個 StringBuffer 類來實現,如 清單 5 所示。
清單 5. StringBuffer 對象
 
function StringBuffer() {
this.buffer = [];
}

StringBuffer.prototype.append = function append(val) {
 this.buffer.push(val);
 return this;
}

StringBuffer.prototype.toString = function toString () {
 return this.buffer.join(“”);
}
對字符串對象(而非值)定義瞭所有的屬性和方法。當您引用一個字符串值的屬性或方法時,ECMAScript 引擎在方法執行前隱式創建一個具有相同值的新字符串對象。此對象隻用於特定請求,當下一次使用字符串值的方法時重新創建。
這種情況下,對那些方法會被調用多次的字符串使用新的語句。
新字符串對象的例子如 清單 6 所示。
清單 6. 創建新字符串對象的例
var str = new String(“hello”);
StringObject.indexOf 比 StringObject.match 快。當搜索簡單字符串匹配時,盡可能用 indexOf 而不用正則表達式匹配。
盡量避免在長字符串中匹配(10KB 及以上),除非您別無選擇。如果您確定隻在字符串某一特定部分匹配,用子串而不是整個字符串比較。
DOM 性能
本章簡要介紹瞭一些可進行調整以提升 DOM 性能的內容。
重繪(Repaint)
當之前不可見的內容變得可見,DOM 就會重繪,反過來也一樣。重繪也稱為重畫。此行為不會改變文檔佈局。不改變元素尺寸、形狀或位置,隻改變外觀也會觸發重繪。
例如,給元素添加邊框或改變背景色就會觸發重繪。重繪的性能代價很大;它需要引擎搜索所有元素以確定哪些可見,哪些必須顯示。
回流(Reflow)
回流是比重繪更顯著的改變。在回流中:
要操作 DOM 樹。
影響佈局的樣式會改變。
元素的 className 屬性會改變。
瀏覽器窗口尺寸改變。
引擎將會對相關元素回流,以確定各部分顯示在哪。子元素也會被回流以反映父元素的新佈局。DOM 中元素後面的元素也會被回流,以計算新佈局,因為它們可能在初始回流時被移動瞭。祖先元素也會因子孫元素大小變化而被回流。最後,所有內容都被重繪。
每次向文檔添加一個元素,瀏覽器都要回流頁面來計算所有內容如何定位、如何呈現。添加的東西越多,回流次數越多。如果能減少單獨添加元素的次數,瀏覽器回流次數就更少,運行也更快。
CSS 性能
將 Cascading Style Sheets (CSS) 放在頂端。如果樣式表放在底部,將最後加載。之前幾秒鐘,頁面都是空白,瀏覽器等待樣式表加載,然後頁面上其他東西才能呈現 — 甚至是靜態文本。
在 Internet Explorer 中,@import 與在底部使用 <link> 效果一樣。我們建議您不要使用。
縮寫屬性
使用縮寫屬性在一個聲明中一次設置幾個屬性,而不是每個屬性用一個聲明。使用縮寫屬性,可以減小文件大小,降低維護量。
例如,可以設置背景、邊框、邊框顏色、邊框樣式、邊框側(頂部邊框、右側邊框、底部邊框、左側邊框)、邊框寬度、字體、頁邊距、輪廓、填充屬性。
CSS 選擇器
CSS 選擇器通過從右到左 移動來匹配。清單 7 所示,瀏覽器必須遍歷頁面中每個錨元素以確定它的父元素 ID 是否是 aElement。
清單 7. 選擇器正從右到左匹配
#aElement > a{
    font-size: 18px;
}
如果從代碼中移除 > ,如 清單 8 所示,性能更糟。瀏覽器要檢查整個文檔中的所有錨。這樣就不是隻檢查錨的父元素,而是順著文檔樹向上查找 ID 為 aElement 的祖先元素。如果正在檢查的元素不是 aElement 的子孫,瀏覽器就要沿著祖先元素的樹查找,直到文檔根部。
清單 8. 如果沒有 >,性能更糟
#aElement a{
    font-size: 18px;
}
最佳實踐
本章將略述能幫助您提升 web 應用程序性能的最佳實踐。
減少 HTTP 請求數
每個 HTTP 請求都有開銷,包括查找 DNS、創建連接及等待響應,因此削減不必要的請求數可減少不必要的開銷。要減少請求數:
合並文件。將總是同時使用的腳本合並到同一個文件中,不會減小總大小,但將會 減少請求數。還可以同樣方法合並 CSS 文件和圖片。可以實現文件自動合並:
在構建階段。用 <concat > 標記,通過運行 Ant 合並文件。
在運行時階段。啟用 mod_concat 模塊。如果 httpServer 是 Apache,用 pack:Tag 作為 JSP 標簽庫來合並 JavaScript 和樣式表文件。(pack:Tag 是一個 JSP-Taglib,可縮減、壓縮及合並資源,如 JavaScript 和 CSS,並將它們在內容或普通文件中緩存。)
使用 CSS Sprites。將背景圖片合並成一個圖片,並使用 CSS background-image 和 background-position 屬性來顯示所需圖片部分。還可使用內聯圖片減少請求數。
後置加載組件
隻呈現需要的組件;其餘可等待。最好不要一次呈現太多組件。
某些情況下,可使用後置加載。由於瀏覽器可視區域外的組件可以後置加載,當這些組建進入可視區域不久後,初始呈現就會失效。
有些 JavaScript 可以在 onload 事件後後置加載,如 JavaScript 中初始呈現後拖動某個元素。
前置加載組件
通過前置加載組件,可以利用瀏覽器的空閑時間請求將來會用到的組件(如圖像、樣式和腳本)。當用戶訪問下個頁面時,如果大多數組件都已在緩存中加載,那頁面加載會快得多。
有兩種前置加載:
無條件:一旦觸發 onload,就取得一些額外組件。
有條件:根據用戶的動作,推測用戶下一步的方向並進行相應的前置加載。
將腳本放在底部
腳本可能會產生問題,因為它們可能會阻礙並行下載。當下載腳本時,瀏覽器不會再啟動其他下載 — 即使那些位於不同主機。將腳本,如樣式表,放在底部,以保證它們在其他下載完成後再下載。
也可以使用延時腳本,這隻有 Internet Explorer 支持。DEFER 屬性表示腳本不含 document.write()。這就告訴瀏覽器他們可以持續呈現。
使用無 cookie 域組件
當瀏覽器發出對靜態圖片的請求,並隨之發送 cookie 時,服務器不會使用那些 cookie。由於這些 cookie 隻會造成不必要的網絡流量,確保用無請求來請求靜態組件。然後使用子域和主機保存這些靜態組件。
將 JavaScript 和 CSS 放在外部
現實世界中使用外部文件通常會使頁面運行更快,因為 JavaScript 和 CSS 文件被瀏覽器緩存。HTML 文檔內聯的 JavaScript 和 CSS 會在每次請求 HTML 文檔時被下載。這減少瞭需要請求的 HTTP 的數量,但增加瞭 HTML 文檔的大小。另一方面,如果 JavaScript 和 CSS 在被瀏覽器緩存的外部文件中,就會減小 HTML 文檔大小,而不會增加請求數。
RIA 小部件性能
主流 RIA Ajax 框架,如 ExtJS、YUI、Dojo 及其他,都提供一些精巧的小部件庫,以增強用戶體驗。與其他框架相比,Dojo 在企業開發領域更強大,這是由於:
Object-oriented programming (OOP) 編碼
跨平臺
本地數據存儲的 Dojo 離線 API 支持
DataGrid、2D 和 3D 圖形(圖表組件提供瞭在瀏覽器展示報表更簡單的方法)
Dojo 在很多網站廣泛使用。我們將使用 Dojo 舉例,分析 RIA 小部件的性能。可根據具體情況使用 Dojo 小部件調整工具,有 Page Speed、Rock Star Optimizer 及 Jiffy。我們強烈建議使用 YSlow 和 Firebug。
YSlow
YSlow 根據一組高性能 web 頁面準則,通過檢查頁面上所有組件,包括由 JavaScript 創建的,來分析 web 頁面性能。YSlow 是一個集成瞭 Firebug web 開發工具的 Firefox 插件;它可提供提升頁面性能的建議、總結組件性能、顯示頁面統計數據並提供用於性能分析的工具。
圖 3 顯示的是 YSlow Grade 選項卡上的信息。
圖 3. YSlow Grade 選項卡

YSlow Grade 面板是 Firefox 插件的一部分

YSlow 的 web 頁面建立在 22 條可測試的規則基礎上,這些規則在下方按重要性和效果排列。研究顯示,按照以下規則,web 頁面響應時間可提升 25% 到 50%:
盡量減少 HTTP 請求數。
使用內容發佈網絡(CDN)。
添加 Expires 或 Cache-Control 頭部。
用 Gzip 壓縮內容。
將樣式表放在頂部。
將腳本放在底部。
避免使用 CSS 表達式。
將 JavaScript 和 CSS 放在外部。.
減少 DNS 搜索。
精簡 JavaScript 和 CSS。
避免使用重定向。
刪除重復的腳本。
配置 ETags。
使 Ajax 可緩存。
使用 GET 進行 Ajax 請求。
減少 DOM 元素數。
消除 404 錯誤。
減小 cookie 大小。
對組件使用無 cookie 的域。
避免使用過濾器。
不在 HTML 中測量圖片大小。
使 favicon.ico 盡可能小,可緩存。
圖 4 中的 YSlow Statistics,對空緩存的訪問用戶和之前訪問過頁面的用戶的頁面大小做瞭對比。
圖 4. YSlow Statistics 選項卡

YSlow Statistics 面板對比頁面大小

Components 選項卡顯示瞭每個組件及相關的性能信息。例如,如果組件被 gzip 壓縮,或 ETag 有內容(如果的話),您都能看到。組件大小和超期時間也顯示在 Components 選項卡中,如 圖 5 所示。
Figure 5. YSlow Components 選項卡

The YSlow Component 面板顯示很多相關信息,包括大小和超期日期

Firebug
Firebug 與 Mozilla Firefox 集成,使您在瀏覽網站時有大量開發工具隨手可用。可以即時編輯、調試、監控 web 頁面中的 CSS、HTML 和 JavaScript。
可以使用 Firebug Net 面板,如 圖 6 所示,監控 web 頁面產生的 HTTP 流量。它向用戶展示瞭所有收集到的和計算出的信息。每個條目表示頁面的一個請求/響應來回。
圖 6. Firebug Net

Firebug Net 面板監控頁面流量

Firebug Console 面板,如 圖 7 所示,提供瞭兩種監控代碼性能的方法。
圖 7. Firebug Console 面板

The Firebug Console 面板幫助監控代碼性能
 
Profile
對於某個特定的函數,使用 Profiler。JavaScript Profiler 是能用來測量每個 JavaScript 代碼執行時間的 Firebug 特性。使用 JavaScript Profiler 來提升代碼的性能,或是查看為什麼某個函數運行時間過長。它與 console.time() ;類似,但 JavaScript Profiler 能提供更多代碼內部過程細節。
console.time()
對於特定代碼段,使用 console.time()。控制臺會顯示您輸入到命令行的命令的結果。可以使用 console.time(timeName) 函數測量某個特定代碼或函數執行多長時間。該特性對於提升 JavaScript 代碼的性能非常有用。清單 9 顯示瞭一個樣例。
清單 9. console.time() 樣例
var timeName = 'measuringTime'; 
console.time(timeName); //start of the timer  
for(var i=0;i<1000;i++){ 
//do something 
console.timeEnd(timeName);  //end of the timer
measuringTime:xxms 將顯示在控制臺。
Dojo 小部件性能
本章將探索能改進 Dojo 小部件性能的方法。
加載成本
如 “Improving performance of Dojo-based web applications" (E. Lazutkin, Feb 2007)中所指出,大多數 Dojo 用戶對它的第一印象是,它非常巨大。例如,dojo-release-1.5.0-src.zip 是 19M,即使壓縮過的 dojo-release-1.5.0.zip 也有 4.5M。最簡版本中的大多數文件都是多餘的,永遠都用不到。所有的 Dojo 版本都有全部 Dojo 文件的拷貝及合並瞭所有常用文件的定制 dojo.js 文件。縮減加載成本的最佳方法是使用合適的 Dojo 版本。
dojo.js 可激活 Dojo 對象,並動態加載其餘模塊,除非它們已經被 dojo.js 中可選部分加載。當瀏覽器第一次加載 dojo.js 文件時,它將會上傳並安裝以下文件:
Dojo 引導代碼
Dojo 加載器
常用模塊
為瞭減小加載時間,需要考慮哪個版本最適合您的應用程序。否則,就要定制一個 Dojo 版本。更多有關 Dojo 文檔信息,見 參考資料 一章。
解析成本
為瞭最小化 Dojo 小部件解析成本,使用以下兩個方法來優化初始化:
Tag 實例化
可以通過添加 dojoType 屬性創建一個帶有 HTML 標簽的 Dojo 小部件,如 清單 10 所示。此方法運行的前提是 dojo.parser 包含在 dojo.require("dojo.parser"); 中,並且 djConfig="parseOnLoad:true"。這是個很簡單的方法,可在輕量級代碼中聲明組件。頁面中所有具有 dojoType 屬性的標簽都會在文檔加載後自動解析。該方法對小型應用程序非常方便,但會顯著增加具有大量 HTML 的 web 應用程序的啟動時間。解析器將訪問所有元素,檢查是否要解析。使用配置文件,如 Firebug 中所提供的。
如果發現在 dj_load_init()、modulesLoaded() 或其他類似初始裝載的內容上花費過多時間,就考慮小部件初始化。
Listing 10. 創建 dojoType 的 Dojo 小部件
id="errorDialog" dojoType="dijit.Dialog" title='dialog1' class="pop-window"/>
代碼實例化
Dojo 是一個 OOP 框架,因此可以使用 new 創建小部件。要創建小部件,必須輸入兩個參數:一個具有屬性的 JSON 對象和要解析的元素。每個小部件至少需要兩個語句。清單 11 是一個樣例。
清單 11. 用 JavaScript new 創建一個 Dojo 小部件
new dijit.Dialog({"title":"dialog1 "},dojo.byId("dialog1"));
提升解析性能
為瞭優化代碼結構和性能,可考慮在創建小部件時提升解析。通過將 parseWidgets 設置為 false 來禁用自動解析,然後創建一個數組來設置元素的 ID,如 清單 12 所示。也可在運行時動態放入新元素的 ID。當文檔加載時,用 dojo.forEach() 解析數組中所有元素。
清單 12. 通過迭代 searchIds 來解析小部件
<head>
….
<script > djConfig = { parseWidgets: false, searchIds: [..] }; </script>
….
</head>
<body onload='dojo.forEach(djConfig.searchIds,
   function(id){dojo.parser.parse(dojo.byId(id));});'>
……..
</body>

解決方案
Dojo 網格的性能問題主要與輸入/輸出操作、大量數據訪問和瀏覽器數據呈現有關。可以通過使用合並網格特性的機制來提升 Dojo 網格小部件的性能。
回顧緩存機制的使用。當數據從數據庫加載到本機時,在內存中保存數據一段時間。這是減小服務器端請求數據的響應時間的好辦法。這樣直到用戶更 新或修改網格中的數據時才發送請求。緩存機制一般是通過 Dojo 網格本身實現的,但用戶對網格進行某種操作時,問題就會發生。以下場景揭示瞭這些問題:
對網格排序
多數情況下,可對網格正確排序,因為網格本身在數據存儲層實現瞭排序函數。但數據存儲會影響緩存。例如,如果網格列的類型是漢字,排序結果可能會不正確,而且網格的性能會由於某些不確定因素而嚴重下降。
解決方案是您自己在數據存儲層重定義排序函數。下方的 清單 13 和 清單 14 演示瞭怎麼做:根據 onHeaderCellMouseDown 函數重寫排序邏輯,呈現數據,並更新網格的頭部標題視圖。
清單 13. 重定義排序邏輯
grid.onHeaderCellMouseDown = function(event){
 var items = DataStore.data.items;
//Sort the "Name" column which might contain characters like Chinese and so on
 if (event.cellIndex == 1) {
  sortAscending = ! sortAscending ;
//Change the string to localestring before comparison with localeCompare method
  if (sortAscending) {
   items.sort(function(m, n){
    return m["name"].toString().
    localeCompare(n["name"].toString());
   });
  }else {
   items.sort(function(m, n){
    return n["name"].toString().
    localeCompare(m["name"].toString());
   });
  }
 }else
 //Sort the "Date" column
 if (event.cellIndex == 2) {
  sortAscending = !sortAscending;
  //Compare the date with milliseconds computed from 1970/07/01
  if (sortAscending) {
   items.sort(function(m, n){
       return  Date.parse(m["date"].toString())
     – Date.parse(n["date"].toString());
   });
  }else {
   items.sort(function(m, n){
    return Date.parse(n["date"].toString())
    – Date.parse(m["date"].toString());
   });
  }
 }
}

清單 14. 呈現數據,更新網格頭部視圖
//"sorColIdx" is the index of the column to be sorted
updateGridAfterSort : function(sortColIdx){
 //Render the data of the grid
 var store = new dojo.data.ItemFileWriteStore(DataStore.data);
 grid.setStore(store, null, null);
 grid.update();
 //Update the header view of the gird
 var headerNodeObjs = document.getElementsByTagName("th");
 for (var i = 0; i < 2; ++i) {
//"gridLayout" is a global array defining the layout of the grid
  var headerNodeObjName = gridLayout[0].cells[0][i].name;
  var headerNodeHtml = ['<p class="dojoxGridSortNode'];
  if (i == sortColIdx){
   headerNodeHtml = headerNodeHtml.concat([' ', (sortAscending ==
    true) ? 'dojoxGridSortUp' : 'dojoxGridSortDown', '"><p
    class="dojoxGridArrowButtonChar">', (sortAscending == true) ?
    '▲' : '▼', '</p ><p class="dojoxGridArrowButtonNode"
     ></p >']);
   headerNodeHtml = headerNodeHtml.concat([headerNodeObjName,
   '</p>']);
   headerNodeObjs[i].innerHTML = headerNodeHtml.join(" ");
   break;
  }
 }
}
在網格中查找
當網格有大量數據時,查找函數將會導致性能低下,尤其是當網格支持實時查找和模糊匹配特性時。解決方案是在它們被轉換成數據存儲中使用的 JSON 對象前,用額外的存儲空間緩存數據;這將避免大量的函數調用,如數據存儲的 getItem。清單 15 顯示瞭一個樣例。
清單 15. 將從數據庫取出的數據緩存到數組中,並查找
//Fetch data from database
getData : function() {
 function callback(ResultSet) {
//ResultSet is an array of records fetched from database and make variable
//rawData refer to it to cache it in memory 
  GlobalVaribles.rawData = ResultSet;
//Convert the raw data ResultSet to JSON for data store use  
  GlobalVaribles.dataJSON = JSONUtil.convert2JSON(ResultSet);
 }
 DBUtil.fetchAll(callback);
}
//Search functionality
search: function(col, value){
 if (value == null || value == "") {
  return;
 }
//Used here
 var rawData = GlobalVaribles.rawData;
 var newResults = [];
 for (var i = 0; i < rawData.length; i++) {
  var result = rawData[i];
//Fuzzy match
  if(result[col].toLowerCase().indexOf(value.toLowerCase()) != -1){
   newResults[newResults.length] = result;
  }
 }
//Render the new results
 GridManager.renderNewResults(newResults);
}
   
延時加載機制
Dojo 網格原本就支持延時加載機制,這可以改善性能並提供更好的用戶體驗。Dojo 網格中的延時加載意味著在數據存儲中呈現某些數據,但不是所有網格在您拖動滾動條時再顯示其餘的數據。
默認情況下,網格不會啟用延時加載機制;必須顯式啟動。清單 16 演示瞭用兩種方法啟動。rowsPerPage 和 keepRows 屬性是關鍵組件。

清單 16. 啟動演示加載機制
             //The programmatic way
             var grid = new dojox.grid.DataGrid({
             store: store, //data store
 structure: gridLayout,
 rowsPerPage: 10,  //Render 10 rows every time
 keepRows: 50,  //Keep 50 rows in rendering cache
}, "grid");  
//The declarative way using HTML label
<table 
dojoType="dojox.grid.DataGrid"
 id="grid" store="store" structure="gridLayout"
 query="{ id: '*' }"
 rowsPerPage="10" keepRows="50">
 <!–  other definitions  –>
</table>
   
前置加載機制
前置加載機制可提前加載其餘的數據,即使用戶隻是臨時使用。對於 Dojo 網格,數據存儲中可能有很多的數據;用戶可能會拖動滾動條查看其餘數據。如果一個頁面中有很多數據,看某一特定行就不方便。使用前置機制和分頁技術可更方 便查看(與 Google 的分頁條類似),並獲得更好的性能。
清單 17 顯示的是分頁技術的基本實現。首先,構造一些 JSON 對象,供數據存儲用於初始分頁條,然後當用戶單擊分頁條的最後一頁時添加一些新的 JSON 對象。
清單 17. 開始時構建一些 JSON 對象並根據需要切換
//Fetch data from database and convert them to JSON objects
getData : function() {
 function callback(ResultSet) {
  GlobalVaribles.rawData = ResultSet;
//"convert2JSONs" method convert the raw data to several JSON objects
//stored in Global array "dataJSONs".
  GlobalVaribles.dataJSONs = JSONUtil.convert2JSONs(ResultSet);
 }
 DBUtil.fetchAll(callback);
}
//Initial status
var dataStore = new dojo.data.ItemFileWriteStore({data:GlobalVaribles.dataJSONs[0]});
var grid = new dojox.grid.DataGrid({
 store: dataStore ,
 structure: gridLayout,
}, "grid");
grid.startup();
//Assuming that the user clicks the i-th item in the paging bar, we just update the data 
//store for the grid simply and the performance is still very good.
dataStore = new dojo.data.ItemFileWriteStore({data:GlobalVaribles.dataJSONs[i-1]});
grid.setStore(dataStore, null, null);
grid.update();
結束語
本文中,您學習瞭如何識別您的 web 應用程序中的一些問題或瓶頸。您現在以瞭解一些工具、竅門和技巧,以用於調整和改善對用戶的性能。

作者“ERDP技術架構”

You May Also Like