隨着Ajax技術的流行,愈來愈多的Web應用使用Ajax技術來提升用戶體驗。使用Ajax技術的一個重要優點是不須要額外的瀏覽器插件支持,只須要使用瀏覽器原生的API,並利用JavaScript來操做便可。使用原生API時會遇到的兩個比較大的問題是瀏覽器兼容性和底層A代PI接口帶來的編程複雜性。一樣的功能在不一樣的瀏覽器上的實現方式是存在差別的。若是一個應用但願支持不一樣的瀏覽器,則開發人員須要添加不少的瀏覽器檢測或嗅探的代碼。好比一樣的事件綁定功能,在IE上使用attachEvent,而在其它瀏覽器上則使用addEventListener。除了兼容性問題以外,瀏覽器提供的原生API的接口通常都比較適合用來執行細粒度的操做。當須要完成一些相對複雜的操做的時候,使用原生API接口會使得代碼比較繁瑣。以一個DOM查詢爲例:在當前文檔樹中查找給定ID的節點的全部給定標籤的直接子節點。對於這樣一個查詢,使用原生DOM API的話,則會須要使用getElementById來查找節點,經過childNodes來獲取子節點列表以及比較節點的標籤名稱等。所要求的碼量會比較大。前端
JavaScript框架的出現,正是爲了解決這兩個比較大的問題,而不一樣的JavaScript框架也提供了各自額外的附加價值。目前可使用的JavaScript框架很是之多,比較流行的也有十多種。這些流行的JavaScript框架包括jQuery、Dojo、YUI、MooTools、Prototype、Ext JS、Google Closure等。這些不一樣的框架有着各自不一樣的優點和不足,也有着對應的不一樣的適用情景和範圍。因爲工做的關係,筆者對Dojo框架的使用最多,對於其它框架也有必定的瞭解。本文的目的是但願澄清一些對於Dojo框架的誤解,從而幫助開發人員選擇合適的框架。jquery
在開始以前,首先簡要介紹一下Dojo框架的基本結構。Dojo框架由四個部分組成:Dojo基本庫、核心庫、Dijit和擴展庫。基本庫包含最基本的功能,核心庫是基本庫的擴展,Dijit是用戶界面庫,而擴展庫則是各式各樣的擴展組件。web
Dojo和其它框架同樣,都試圖知足Ajax應用開發中的最基本的需求。這些基本的需求包括前面提到的瀏覽器兼容性和原生API的接口粒度問題,以及一些典型的應用場景。具體來講,應該包括下面一些功能集:JavaScript語言加強、XMLHttpRequest封裝、DOM查詢與操做和事件處理等。而瀏覽器兼容性體如今這些功能集在不一樣瀏覽器上的效果是同樣的。ajax
從Dojo框架來講,對這些功能集的支持是比較豐富的。在JavaScript語言加強方面,對數字、字符串、日期類型、數組和JavaScript方法等有不少的加強功能。在I/O傳輸方面,除了經常使用的XMLHttpRequest 以外,還支持iframe和<script>等。dojo.query提供了相似於jQuery的DOM查詢和操做的能力。 dojo.connect不但能夠用來綁定DOM元素上的事件,還能夠鏈接到JavaScript方法的執行上。編程
上面提到的這些基本功能都出如今Dojo基本庫和核心庫中。打包壓縮以後的代碼大小在80K左右,不會對整個頁面的代碼量形成很大的影響。數組
面向對象的編程思想是目前比較流行的一種編程方法學。這種編程思想也被主流的編程語言所支持,包括Java、C++和C#等。不少開發人員都習慣於用面向對象編程思想中的類和對象的概念去進行分析和設計,再用相應的編程語言來完成實現。面向對象編程思想中的封裝、繼承和多態等概念,也比較適合對真實的問題域進行分析和抽象。在某些Ajax應用中,前端部分的邏輯比較複雜,同時也須要實現一部分業務邏輯。所需的代碼量已經不是幾個簡單的方法這個級別,而須要進行完整的建模、分析和設計。不少開發人員會天然而然的使用面向對象的編程思想對Ajax應用的前端進行分析和設計。可是JavaScript語言並非一門面向對象的編程語言,它在不少方面都不一樣於傳統的面向對象編程語言。所以在從分析和設計到實現的過程當中,會出現阻抗不匹配的狀況。對於這種不匹配的狀況,解決的辦法不外乎兩種:一種是改變分析和設計時的思路,而另一種則是對JavaScript語言進行面向對象方面能力的加強。瀏覽器
JavaScript語言在設計的時候,就帶有一些面向對象編程語言的影子,如new操做符和經過原型(prototype)能夠實現的繼承機制等。經過JavaScript的這些語言特性,能夠實現完整的面向對象能力。Dojo框架所提供的面向對象方面的能力很是完備。最典型的用法是能夠經過dojo.declare()方法來聲明一個類,而且能夠支持多繼承。使用Dojo能夠很快的寫出經典的支持多繼承的面向對象的示例,如:服務器
dojo.declare("Human", null, { think : function() {} }); dojo.declare("Machine", null, { work : function() {} }); dojo.declare("Robot", [Machine, Human], { turingTest : function() {} });
Dojo經過其面向對象JavaScript的支持,在必定程度上解決了前面提到的阻抗不匹配的問題。可是在全面使用Dojo提供的面向對象JavaScript 的能力的時候,要注意會帶來的一些風險。首先要理解的是函數在JavaScript中是一等公民,能夠做爲對象的屬性以及函數的參數和返回值來使用。 JavaScript中的閉包也是一個很是強大的概念,妥善使用的話能夠寫出簡潔而強大的程序。若是徹底按照Dojo所抽象出來的面向對象的方式來使用 JavaScript,會丟失掉JavaScript語言自己的一些好的特質。因此不建議開發人員一開始就深刻到Dojo的面向對象JavaScript 的世界裏面,而是首先多瞭解一些JavaScript語言自己的特徵。好比理解JavaScript中的原型鏈(prototype chain)、this的含義、new操做符、執行上下文(execution context)和做用域鏈(scope chain)等。不然的話,一旦造成了思惟定勢,可能會沒法理解其它框架或是庫的實現方式,畢竟不是全部的庫都採用了Dojo這樣的方式來實現。其次要認識到在性能方面可能帶來的影響。熟悉Java的開發人員可能都習 慣於在設計的時候使用不少個細分的Java類,這些類之間經過精細的協做來完成具體的任務。這對Java來講是合理的。而對於運行在瀏覽器中的 JavaScript這種解釋執行的語言來講,過多的對象和消息傳遞會對性能形成必定的影響,而性能又是Ajax應用中須要關注的重要因素。閉包
面向對象編程的思想進入到Web應用的前端開發領域,是一件好的事情。它使得廣大前端開發人員能夠用本身熟悉的方式來設計和開發Web前端。可是在 JavaScript語言自己和瀏覽器這個運行平臺的雙重限制下,須要適度的使用,不過將來的前景是樂觀的。JavaScript是ECMAScript的方言之一,目前的實現基本都遵循的是ECMAScript第三版規範。而ECMAScript第五版規範已經發布。值得一提的是,ECMAScript第四版嘗試在JavaScript中引入類、包和名稱空間等概念,不過因爲各類緣由被放棄了。而第四版的這些思想造成了新的正在開發中的ECMAScript Harmony項目。按照標準化過程的速度,短時間以內JavaScript語言是不會擁有傳統面向對象編程語言的類的結構,而包和名稱空間的結構則須要等待更長的時間。不過這一天終會到來。隨着V8、Chakra、SquirrelFish和Carakan等新的JavaScript引擎的出現,JavaScript語言自己的執行性能將會有大幅度的提高。這兩個方面的改進會使得以面向對象的思想編寫JavaScript程序變得更加天然。框架
Dojo是一個龐大和複雜的庫,其中包含數以百計的模塊。每一個模塊都有本身的源代碼、測試用例、演示頁面和文檔說明等。從這個角度來講,Dojo的複雜度高於jQuery等其它框架。對於Ajax應用來講,有兩種常見的風格:Ajax Lite和Ajax Deluxe。對於Ajax Lite風格的Ajax應用來講,jQuery等輕量級框架是比較好的選擇,能夠很方便的對頁面作出修改。只使用Dojo基本庫也是不錯的選擇。對於Ajax Deluxe風格的應用來講,Dojo能夠體現出它的價值。在開發風格的複雜Ajax應用時,一套完整的用戶界面組件庫是很是有必要的,能夠極大節省開發人員的時間。在這個層次上,Dojo和jQuery採用了不一樣的作法。jQuery很是小巧靈活,暴露給開發人員的概念很是少。$、CSS選擇器和方法級聯,就已經差很少是所有了。社區也貢獻了很是多的jQuery插件,豐富了jQuery自己的功能。這是一種自下而上的作法,先有一個穩健的基礎,再依靠社區的力量發展壯大。Dojo的作法則正好相反。Dojo中已經集成了不少模塊,知足各類不一樣的需求。這些模塊背後都體現了相同的設計思想。以用戶界面與數據的關係爲例,Dojo定義了dojo.data API來抽象異構數據源的訪問接口。須要訪問數據的用戶界面組件都經過此API來訪問數據。這種作法帶來的問題是暴露給開發人員的概念過多,給開發人員的感受是完成一件簡單任務的起步就很是困難。不過這種作法也爲框架自己的維護和擴展帶來了方便。當構建一個複雜的Ajax應用的時候,這種複雜性有時候是很是必要的,尤爲在團隊工做的時候。對於一個複雜的問題,老是會須要一些稍微複雜的設計來保證解決方案的可維護性。與其選擇本身去處理它,還不如交給一個設計良好的框架來完成。
對於開發Ajax Lite風格的Ajax應用來講,也能夠從Dojo基本庫開始。當須要的時候再考慮Dijit庫。
前面提到了Dojo的複雜性,這種複雜性會使得開發人員很難在較短的時間內入門。開發人員要理解和接受的概念過多。Dojo框架自己也提供了兩種類型的編程風格,即前面提到的面向對象和函數式的方式。Dojo基本庫和核心庫比較多的採用的函數式的風格,好比dojo.connect()、dojo.xhrGet、 dojo.declare()和dojo.query()等。開發人員能夠把這些方法當成工具來使用。對於Dojo基本庫和核心庫來講,只須要查看相關的 API說明文檔就能夠知道每一個方法的參數、返回值和須要注意的地方。Dijit庫則使用的是面向對象的風格。Dijit庫包含的是一些用戶界面組件,組件內部封裝了相關的邏輯。開發人員須要經過new操做符來在頁面上建立出組件的實例。這樣的使用方式對熟悉Java圖形界面組件庫,如SWT/JFace和 Swing的開發人員來講,是比較好理解的。而兩種編程風格雜糅在一塊兒,會對開發人員的理解形成必定的問題。在這點上,jQuery UI的作法就更加可取一些。在Dijit裏面建立一個對話框並打開的作法是:
var dialogNode = dojo.query("#dialogNode")[0]; var dialog = new dijit.Dialog({}); dialog.open();
而在jQuery UI裏面,使用的方式是:
$("#dialogNode").dialog({autoOpen : false}); $("#dialogNode").dialog("open");
jQuery UI在編程風格上與jQuery是類似的,採用的都是函數式的風格。這種一致性對開發人員來講是更加合適的。
在Ajax應用的前端界面部分,少不了用戶界面組件的支持。HTML語言自己提供了一些基本的元素,包括常見的div、span和表單元素等。使用這些基本元素能夠構造出複雜的用戶界面。可是相對於桌面應用開發時可使用的組件來講,HTML語言的這些元素仍是過於基本,沒法快速高效的進行開發。好比一些常見的界面組件,如菜單、對話框、樹形控件、表格控件、日期和時間選擇器和富文本編輯器等,都須要開發人員本身來實現,不只耗時並且質量也比較難以保證。對於這種狀況,Dojo框架提供了本身的用戶界面組件編程模型Dijit,以及一些高質量可定製的標準用戶界面組件。經過使用和定製這些標準組件,能夠很快速的構建出應用的界面。開發人員也能夠根據編程模型,開發出本身應用所需的特有組件。
從這個角度來講,Dojo框架但願提供的是與桌面開發類似的用戶界面組件庫,比較適合在集成開發環境中使用。開發人員經過拖拽的方式來添加組件,並設置組件的相關屬性。經過這種方式,能夠幫助開發人員更快的構建複雜的Ajax應用。Dijit庫的好處在於提供了一個設計良好的Web應用前端組件編程模型,以及在這模型基礎之上的衆多參考實現。這就爲建立一個良好的組件共享平臺打下了基礎。實際上,在Dojo擴展庫中就已經有很多由社區貢獻出來的組件。這個編程模型的一些優勢在於:
從前端開發人員的角度來講,若是對用戶界面的組件化是一個必要的設計考慮,則Dijit是一個比較好的起點。
對於Web應用來講,性能是一個很是重要的因素。既然JavaScript庫是目前Ajax應用開發中必不可少的一部分,那麼性能方面的差異會成爲選擇的重要因素。通常對Dojo框架的認識是速度很慢。實際上,影響Web應用性能的因素很是多,包括HTTP請求的個數、請求響應內容的大小、JavaScript代碼的執行時間、頁面元素的從新佈局和排列次數等。把頁面的速度過慢單純歸咎於 JavaScript庫自己,是有失偏頗的。
對於Dojo庫的一個比較常見的見解是Dojo庫過於龐大,須要加載比較多的資源文件,致使頁面的加載速度過慢。確實,與jQuery和Prototype等JavaScript庫相比,Dojo庫分發包偏大。Dojo 1.5的分發包是2M,而jQuery 1.4.4壓縮以後的大小才26K。不過二者的功能是不一樣的。Dojo庫所提供的功能更多,所包含的代碼量天然更大。形成這一緣由的問題在於開發環境和部署環境的不一樣。對於jQuery來講,開發環境和部署環境是相同的,只須要複製單個JavaScript文件便可。而對於Dojo則沒有這麼簡單,這中間缺乏的步驟是構建過程。
Dojo採用的是模塊化的設計,其中包含很是多的模塊,分佈在Dojo基本庫、核心庫、Dijit庫和擴展庫中。經過dojo.require能夠聲明在頁面中須要加載的模塊。這個加載過程會須要從服務器端下載所需的JavaScript文件,從而致使在運行時過多的HTTP請求。Dojo的構建系統會把來自不一樣模塊的JavaScript文件打包在一個文件中,只須要在頁面上引用打包好的單個JavaScript便可。使用Dojo的構建過程,須要下載Dojo SDK,在utils/buildscripts/profiles目錄下面添加一個構建文件,如myDojo.profile.js。在該文件中聲明所須要包含的模塊,如:
dependencies = { layers: [ { name: "dojo.js", dependencies: [ "dijit.layout.BorderContainer", "dijit.layout.ContentPane", "dojox.layout.ExpandoPane", "dojox.image.Lightbox" ] } ], prefixes: [ [ "dijit", "../dijit" ], [ "dojox", "../dojox" ] ] }
再經過運行
build profile=myDojo
action=release就能夠啓動構建過程,最後在release目錄下面的就是能夠直接複製到部署環境的Dojo庫。Dojo的構建過程使用的是運行在Rhino上的JavaScript代碼,能夠很好的與Apache Ant集成。也能夠選擇使用其它圖形化構建工具,如:Dojo Toolbox。