三大UI架構Dijit、ExtJS、jQuery UI全方位對比

來源:互聯網
上載者:User

三大UI架構Dijit、ExtJS、jQuery UI全方位對比

 Dijit、ExtJS、jQuery UI 簡介

  Dojo 是開源 ja vasc ript 庫中起步較早的先行者之一。由 Alex Russell, David Schontzler, Dylan Schiemann 等人於 2004 年創立。Dojo 具有類似 Java 的包機制 (packaging system), 將 JS 代碼根據功能進行了模組化。主要包含 Dojo、Dijit 以及 Dojox 三個包。其中 Dojo 包提供穩定的核心 API,Dijit 包提供各類 UI 控制項,Dojox 包則囊括了一系列實驗性的 API 及控制項(其中不乏一些得到長期維護、穩定性已相當高的包,如 dojox.charting 包和 dojox.grid 包等)。在 Dojo 1.7 版本中,Dijit 包的內部結構被進行了更細的模組拆分和重構,但由於撰寫本文時其尚未發布,本文中的 Dijit 相關內容仍將基於 Dojo 1.6.1 版本。

 

  ExtJS 是當今一套被廣泛應用於前端開發的 Ajax 以及控制項架構,其曆史可以追溯到 Yahoo! User Interface。在 Jack Slocum 的耕耘下,ExtJS 逐漸成長。自從 ExtJS 的 2.0 版本發布後,其使用範圍逐漸擴充到世界各地。3.X 版本中推出了更多易用的控制項,ExtJS 的優勢在於其強大的控制項陳列庫,以及其對於各種前台功能的封裝,形成了完整的一套物件導向風格的 JS 控制項陳列庫。隨著和 Sencha 合并,ExtJS 也向觸控螢幕發展,不過其 Ext JS 庫的發展從未停止。如今的 ExtJS 4.0 提供了更完整的 ja vasc ript API 庫,減少對 Array、Function、String 等底層類的重寫,大大的減少了不同的 JS 庫之間的衝突問題。由於 4.0 版本不向下相容,對升級造成了一定的影響,筆者還沒有機會去深入使用 ExtJS 4.0 版本,因此本文著重介紹的是 ExtJS 3.X 版本。

 

  jQuery UI 是 jQuery 的官方 UI 控制項陳列庫。jQuery 的大名在業內可謂是無人不知無人不曉。自 2006 年發布了其第一個穩定版之後,其輕量、易用的特點使其深入人心。jQuery UI 於 2007 年發布,它完全基於 jQuery 提供的外掛程式機制,提供了底層互動及動畫功能以及一些可定製樣式的 UI 控制項。雖然提供的控制項數量不多,但它們都具備了 jQuery 小巧的特點,其使用風格也與 jQuery 核心 API 一致。撰寫本文時,其最新的穩定版本為 1.8.16,本文中關於 jQuery UI 的內容都基於該版本。

 

  控制項的使用方式

  在討論各個控制項陳列庫的架構實現之前,首先讓我們從使用者的角度來看看 Dijit、ExtJS、jQuery UI 控制項的的使用方式,對它們有一個直觀的瞭解。

  控制項的使用無外乎建立控制項、操作控制項,而在建立控制項之前,我們往往需要先載入控制項資源。下面就讓我們從控制項資源載入開始聊起(控制項 CSS 檔案編寫與載入不在本文範圍內)。

 

  控制項資源載入

  Dijit 篇:藉助於 Dojo 提供的自動載入模組依賴項的機制,載入 Dijit 控制項所需資源非常簡單,使用者並不需要瞭解一個控制項究竟需要哪些 JS 檔案的支援,只需向頁面添加 Dojo 核心檔案 dojo.js 並使用 dojo.require 函數匯入控制項對應模組即可。

 

  清單 1. Dijit 資源載入

  <sc ript type="text/ja vasc ript" src="lib/dojo/dojo.js"></sc ript>

  <sc ript type="text/ja vasc ript">

  dojo.require("dijit.form.Button");

  </sc ript>

  上述代碼將自動載入 Button 控制項所依賴的所有 JS 檔案。

 

  ExtJS 篇:ExtJS 本身沒有一套完整的自動載入依賴資源的機制,在大多數情況下,使用者都是使用完整的 ExtJS 庫,只需要匯入 /ExtJS/adapter/ext/ext-base.js 和 /ExtJS/ext-all.js 這 2 個檔案即可。一般情況下為了方便調試,會使用 ext-base-bug.js 和 ext-all-debug.js 這 2 個檔案。

 

  清單 2. ExtJS 資源載入

  <sc ript type="text/ja vasc ript" src="JsLib/ExtJS/adapter/ext/ext-base-debug.js"></sc ript>

  <sc ript type="text/ja vasc ript" src="JsLib/ExtJS/ext-all-debug.js"></sc ript>

 

  當然為了節省資源也可以只載入部分的 ExtJS 資產庫,ExtJS 提供了一個名為 ext.jsb2 的檔案(該檔案描述了各個 JS 檔案之間的依賴情況), 讓使用者查詢各個檔案之間的依賴情況,方便使用者進行 ExtJS 控制項的單個匯入。

 

  jQuery UI 篇:由於 jQuery 也沒有提供一套完整的自動載入依賴資源的機制,因此使用者需要手動將所使用控制項的依賴資源逐一匯入頁面。以 jQuery UI 中的 button 控制項為例,需要通過手動為頁面添加如下代碼匯入所需 js 檔案。

 

  清單 3. jQuery UI 資源載入

  <!- - 匯入 jquery core -->

  <sc ript type="text/ja vasc ript" src="lib/jquery/jquery-1.6.2.js"></sc ript>

  <!- - 匯入 Button 控制項所依賴的 JS 資源 -->

  <sc ript type="text/ja vasc ript" src="lib/jquery/ui/jquery.ui.core.js"></sc ript>

  <sc ript type="text/ja vasc ript" src="lib/jquery/ui/jquery.ui.widget.js"></sc ript>

  <sc ript type="text/ja vasc ript" src="lib/jquery/ui/jquery.ui.button.js"></sc ript>

 

  這樣手動載入資源的方式需要使用者清楚瞭解一個控制項依賴哪些資源項,這在使用某些依賴項較多的控制項,如 dialog 時會帶來困擾。雖然在最終發布的產品中,往往會將頁面中所有使用到的 JS 代碼進行合并壓縮,使用者僅需要在頁面中匯入合并壓縮過的 JS 檔案即可,但使用者仍需要在瞭解頁面需要哪些資源之後再對其進行合并壓縮(當然使用者也可以選擇一次性將所有 jQuery UI 的代碼合并壓縮到一個檔案中)。

 

  控制項建立

  Dijit 篇:Dijit 控制項的建立方式有兩種,編程式(programmatic)以及聲明式(declarative)。

  使用編程方式使用 Dijit 控制項與使用傳統物件導向語言進行 UI 編程非常類似。通常只需要提供一個 DOM 節點、一個散列參數表並使用 new 關鍵字建立一個所需的 dijit 控制項對象即可。

 

  清單 4. Dijit 使用 new 關鍵字建立 Button 控制項

  <html>

  <head>

  <sc ript type="text/ja vasc ript">

  dojo.addon load(function(){

  var button = new dijit.form.Button({

  id: "programmatic",

  label: "This is a button"

  }, "buttonNode");

  });

  </sc ript>

  </head>

  <body>

  <div>

  <button id="buttonNode">

  </button>

  </div>

  </body>

  </html>

  上述代碼將會建立一個 Button 控制項,並將 id 為 buttonNode 的 button 標籤元素替換為執行個體化的控制項的 DOM 樹。而 button 變數則指向該控制項執行個體的引用。此外還可以先建立控制項執行個體,再將其插入到頁面的 DOM 樹中。

 

  清單 5. Dijit 使用 new 關鍵字建立 Button 控制項

  <html>

  <head>

  <sc ript type="text/ja vasc ript">

  dojo.addon load(function(){

  var button = new dijit.form.Button({

  id: "programmatic",

  label: "This is a button"

  });

  button.placeAt("buttonContainer");

  });

  </sc ript>

  </head>

  <body>

  <div>

  <p id="buttonContainer">

  </p>

  </div>

  </body>

  </html>

  上述代碼會建立一個 Button 控制項執行個體並將其 DOM 樹其插入到 id 為 buttonContainer 的 p 標籤元素之下。

 

  使用聲明方式使用 Dijit 控制項時,需要為 HTML 標籤添加 data-dojo-type 以及 data-dojo-props 屬性,其中 data-dojo-type 表示所要產生控制項的名稱,data-dojo-props 包含產生控制項所需的構造參數。使用此種方法建立 Dijit 控制項時,可以在匯入 Dojo 核心檔案時通過 parseon load 屬性配置是否自動執行個體化頁面上所有控制項。

 

  清單 6. 開啟 parseon load 屬性,自動建立控制項

  <html>

  <head>

  <sc ript type="text/ja vasc ript" src="lib/dojo/dojo.js" data-dojo-config="parseon load:

  true"/>

  </head>

  <body>

  <button data-dojo-type="dijit.form.Button"

  data-dojo-props= 'id: "declarative"; label: "This is a button"’ />

  </body>

  </html>

  上述代碼將會在頁面載入完畢後自動執行個體化一個 Button 控制項。當使用者選擇關閉 parseon load 選項時,可以通過手動方式執行個體化所需要的控制項。

 

  清單 7. 關閉 parseon load 屬性,手動建立控制項

  <html>

  <head>

  <sc ript type="text/ja vasc ript" src="lib/dojo/dojo.js" data-dojo-config="parseon load:

  false"/>

  <sc ript type="text/ja vasc ript">

  dojo.addon load(function(){

  dojo.parser.parse();

  });

  </sc ript>

  </head>

  <body>

  <button data-dojo-type="dijit.form.Button"

  data-dojo-props= 'id: "declarative"; label: "This is a button"’ />

  </body>

  </html>

  無論是否啟用 parseon load 選項,其本質都是使用 dojo.parser 這個對象對頁面進行掃描,解析 HTML 標籤中的屬性,並根據這些屬性內容執行個體化控制項。需要注意的是,dojo.parser 並不是 Dojo base 的一部分,也就是說之前置入的 Dojo 核心檔案 dojo.js 並不包含 dojo.parser 模組,因此通常情況下使用 dojo.parser 的話需要額外添加代碼匯入 dojo.parser 模組。

 

  清單 8. 匯入 dojo.parser 模組

  dojo.require("dojo.parser");

  然而在使用 Button 控制項時,由於我們已經匯入了 dijit.form.Button 模組 ,Dojo 會為我們自動載入所有該模組依賴的資源,其中就包括 dojo.parser 模組對應的 JS 檔案。

  ExtJS 篇:ExtJS 控制項的產生方式基於使用 new 關鍵字建立一個 ExtJS 控制項對象,將其放入需要渲染的 DOM 節點中。例如:

  清單 9. ExtJS 使用 new 關鍵字建立 Button 控制項

  <sc ript type="text/ja vasc ript">

  var button = new Ext.Button({

  id: 'button',

  text: 'button',

  renderTo: Ext.getBody()

  });

  </sc ript>

  上述代碼中,通過賦予 renderTo 參數一個頁面的 DOM 節點,將一個 Ext.Button 對象添加到 body 元素中,至此一個簡單的 ExtJS 控制項完成了。

  此外 ,ExtJS 還允許使用者通過 add() 和 doLayout() 方法,向容器控制項(繼承自 Ext.Container 類的控制項)中添加預設 renderTo 屬性的子控制項。

 

  清單 10. ExtJS 向容器控制項添加子控制項

  <sc ript type="text/ja vasc ript">

  var mainPanel = new Ext.Panel({

  renderTo: Ext.getBody()

  });

  var button = new Ext.Button({

  id:'button'

  });

  mainPanel.add(button);

  mainPanel.doLayout();

  </sc ript>

  上述代碼首先將 mainPanel 對象渲染到 body 元素中,之後通過 add() 和 doLayout() 方法將預設 renderTo 屬性的 button 對象添加到 mainPanel 對象中,並重新渲染 mainPanel 對象,此時 button 對象也會被渲染到頁面上。

  ExtJS 沒有像 Dijit 那樣提供通過解析 HTML 標籤的方式建立控制項,但是提供了簡單的反射機制,使使用者可通過描述符來產生控制項。

 

  清單 11. ExtJS 通過描述符產生控制項

  <sc ript type="text/ja vasc ript">

  var mainPanel = new Ext.Panel({

  items: [{

  xtype: 'button',

  id: 'button'

  }],

  renderTo: Ext.getBody()

  });

  </sc ript>

  上述代碼首先執行個體化一個 ExtJS 的 Panel 控制項並在其 items 屬性中添加了一段關於 button 控制項的描述符,在 mainPanel 對象渲染的過程中,會遍曆 items 數組中的每一個對象,如果對象沒有被執行個體化,則會尋找描述符對象中的 xtype 屬性。而後,在控制項建立的過程中,Ext.ComponentMgr 的 create() 方法會根據描述的 xtype 屬性尋找在 Ext.reg 中註冊過的控制項類,通過反射的方式建立一個對應的控制項執行個體。

 

  jQuery UI 篇:jQuery UI 控制項的使用方式秉承了 jQuery 一貫簡潔的風格。它並不提供類似於 dojo.parser 這樣的工具類來掃描頁面並根據 HTML 標籤自動產生控制項執行個體,也不像傳統的物件導向語言那樣使用 new 關鍵字來建立控制項,而是通過 jQuery 外掛程式常用的鏈式書寫方式來建立控制項。

 

  清單 12. jQuery UI 建立 Button 控制項

  <html>

  <head>

  <sc ript type="text/ja vasc ript">

  $(function){

  $("#buttonNode").button({

  label: "button"

  });

  });

  </sc ript>

  </head>

  <body>

  <div>

  <button id="buttonNode"></button>

  </div>

  </body>

  </html>

  上述代碼首先使用 jQuery 核心方法 $() 擷取頁面中所有符合查詢條件的 HTML DOM 節點(本例中只有一個 id 為 buttonNode 的 DOM 節點符合條件),並將返回的 DOM 節點數組封裝成一個 jQuery 對象。之後調用 $.ui.button 外掛程式為 jQuery 對象提供的 button 方法根據傳入的散列參數表為這些節點建立 $.ui.button 控制項。

 

  控制項操作

  Dijit 篇:在建立 Dijit 控制項之後,使用者可以通過 dijit.byId、dijit.findWidgets、dijit.byNode、dijit.getEnclosingWidget 等方法擷取控制項執行個體。

  清單 13. 擷取 Dijit 控制項對象

  // 擷取 widget id 為 programmatic 的控制項

  var widget = dijit.byId("programmatic");

  // 擷取 body 標籤下的所有控制項

  var widgets = dijit.findWidgets(dojo.body());

  // 擷取 DOM 樹根節點為以 node 的控制項

  var widget = dijit.byNode(node);

  // 擷取 DOM 樹中包含 node 節點的控制項

  var widget = dijit.getEnclosingWidget(node);

  擷取控制項執行個體之後可以像使用 Java 類那樣調用控制項方法。並使用 get、set 方法來擷取/設定控制項的屬性。

 

  清單 14. Dijit 控制項屬性擷取/設定及方法調用

  // 調用控制項方法

  widget.someMethod();

  // 使用 get 擷取控制項屬性

  var value = widget.get(attributeName);

  // 使用 set 設定控制項屬性

  widget.set(attributeName, value);

  ExtJS 篇:ExtJS 並沒有像 Dijit 一樣提供了通過 DOM 節點尋找控制項的方法,而是只提供通過控制項 id 號擷取控制項對象的方法。

 

  清單 15. 擷取 ExtJS 控制項對象

  // 擷取控制項對象

  var button = Ext.getCmp("button");

  Ext.getCmp 方法返回的就是一個完整的 ExtJS 的控制項對象,包含了控制項對象的所有變數及方法。與 Dijit 不同的是,ExtJS 的成員變數大多是通過使用變數名去擷取/設定的,僅對部分屬性提供了對應的 get/set 方法(其原因和內容將在後文的“屬性擷取/配置方法”章節中具體闡述), 而 ExtJS 的控制項方法調用還是與 Java 的方法調用類似的。

 

  清單 16. ExtJS 控制項屬性屬性擷取 / 設定及方法調用

  // 擷取控制項成員變數,直接存取成員變數

  var buttonText = button.text;

  //button 控制項為 width 屬性添加了 setWidth 方法,以便 width 屬性改變後,對 DOM 節點進行處理。

  button.setWidth(100);

  // 調用控制項成員函數,類似 Java 的對象方法調用方式

  button.focus();

  jQuery UI 篇:操作 jQuery UI 控制項的方式與建立 jQuery UI 控制項的方式非常相似。

 

  清單 17. jQuery UI 控制項方法調用

  <html>

  <head>

  <sc ript type="text/ja vasc ript">

  $(function){

  // 為 button 標籤建立 Button 控制項

  $("#buttonNode").button({

  label: "button"

  });

  // 調用 Button 控制項的 disable 方法

  $("#buttonNode").button("disable");

  });

  </sc ript>

  </head>

  <body>

  <div>

  <button id="buttonNode"></button>

  </div>

  </body>

  </html>

  上述代碼中,先後調用了兩次 button 方法,但其含義完全不同。第一次調用 button 方法時,傳入了一個散列參數表,為對應節點建立了 $.ui.button 控制項。第二次調用 button 方法時,參數為一個字串,此時 jQuery 調用了與字串同名的控制項成員方法。

 

  jQuery UI 並沒有為控制項屬性提供預設的 get/set 方法,但使用者可以通過如下方式擷取/設定控制項屬性:

  清單 18. jQuery UI 控制項屬性擷取 / 設定

  // 調用 option 方法擷取 $.ui.button 控制項的屬性工作表

  var options = $("#buttonNode").button("option");

  // 設定 buttonNode 節點對應的 $.ui.button 控制項的 label 屬性

  $("#buttonNode").button({

  label: "changed label"

  });

  上述代碼中第二次調用 button 方法時雖然傳入的是一個散列參數表,但由於之前已經為 id 號為 buttonNode 的 DOM 節點建立過 $.ui.button 控制項,因此不會再次建立控制項對象,而是取出已建立的控制項對象,並設定其對應的屬性。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.