你很喜歡Gmail和Trello之類(lèi)的單頁(yè)面應(yīng)用,但是不太確定該從何開(kāi)始。也許你的JavaScript代碼是如此的雜亂無(wú)章,以致于你很想在下一個(gè)項(xiàng)目上嘗試下JavaScript MVC庫(kù)和框架,卻苦于沒(méi)有頭緒?我正在撰寫(xiě)一本單頁(yè)面應(yīng)用的書(shū),所以我閱讀了大量網(wǎng)上的相關(guān)資料。在這里我嘗試提供一些看法,希望可以幫助你下決定。 簡(jiǎn)介這里討論的是時(shí)下最熱的框架,AngularJS、Backbone、Ember和Knockout。同時(shí)提到了Batman、CANjs、Meteor和Spine,但是沒(méi)有詳細(xì)展開(kāi)。 我們從多個(gè)不同的角度考察每個(gè)項(xiàng)目,包括社區(qū)、領(lǐng)導(dǎo)、成熟度、大小、依賴(lài)、互操作性、啟發(fā)、理念和特性。 社區(qū)社區(qū)是一個(gè)衡量任何開(kāi)源項(xiàng)目健康程度的重要指數(shù)。以下表格顯示了GitHub上每個(gè)項(xiàng)目的關(guān)注者數(shù)量。 你當(dāng)然不該僅僅根據(jù)這些數(shù)據(jù)做決定,但是它們確實(shí)為你提供了關(guān)于這些框架的一些感性認(rèn)識(shí): 最主流:
正在高速成長(zhǎng)的:
關(guān)注總量較低但是增長(zhǎng)迅猛的:
增長(zhǎng)性特別值得注意的是AngularJS 13個(gè)月以來(lái)的驚人增長(zhǎng)(379%)。在你做決定的時(shí)候要考慮上這一點(diǎn)。下面的圖表比較了13個(gè)月以來(lái)GitHub關(guān)注者的增長(zhǎng)速度,可以看出某個(gè)項(xiàng)目的社區(qū)成長(zhǎng)的速度??紤]到原先的社區(qū)大小,Meteor(130%)、Ember(104%)、Knockout(76%)和Backbone(64%)的增長(zhǎng)速度也很驚人。 領(lǐng)導(dǎo)了解項(xiàng)目的核心開(kāi)發(fā)者的背景,他們創(chuàng)建框架時(shí)嘗試解決的問(wèn)題,有助于你欣賞他們?cè)谠O(shè)計(jì)上的決策和動(dòng)機(jī)。例如,David Heinemeier Hansson,流行的Ruby on Rails框架的締造者,是37signals的簽約開(kāi)發(fā)者,從事項(xiàng)目設(shè)計(jì),每周只有10小時(shí)能花在開(kāi)發(fā)框架上。Ruby on Rails事實(shí)上是從他和37signals的簽約工作中提取出來(lái)的。這一背景有助于你理解為什么這個(gè)框架需要將開(kāi)發(fā)效率提升到極限——這意味這使用大量的約定(已經(jīng)做出的決定)和支架程序(生成的代碼)。下面,我將介紹JavaScript MVC 框架的締造者,也許也能激起你對(duì)他們的工作的欣賞。 BackboneJeremy Ashkenas和DocumentCloud Jeremy Ashkenas是CoffeeScript編程語(yǔ)言、Backbone.js JavaScript框架和Underscore.js JavaScript工具庫(kù)的創(chuàng)立者。根據(jù)維基百科,他現(xiàn)在在NYTimes/DocumentCloud從事互動(dòng)新聞方面的開(kāi)發(fā)。 圖片來(lái)自The Canadian University Software Engineering Conference。 AngularJSAngularJS最初由Google的Mi?ko Hevery和Adam Abrons于2009年開(kāi)發(fā),當(dāng)時(shí)是一個(gè)在線(xiàn)JSON存儲(chǔ)服務(wù)的一部分。Abrons后來(lái)離開(kāi)了這個(gè)項(xiàng)目,但是在Google工作的Hevery繼續(xù)開(kāi)發(fā),和Google的員工Igor Minár、Vojta Jína一起維護(hù)這個(gè)庫(kù)。 圖片來(lái)自Devoxx 2012 KnockoutSteve Sanderson是Knockout的原作者。Steve Sanderson現(xiàn)在為微軟工作,他所在的團(tuán)隊(duì)開(kāi)發(fā)ASP.NET、IIS和其他web項(xiàng)目。他以前以外包開(kāi)發(fā)者或顧問(wèn)身份為Bristol周邊的客戶(hù)開(kāi)發(fā).NET下的軟件,他還為Apress寫(xiě)了一些書(shū),包括《Pro ASP.NET MVC框架》。 圖片來(lái)自Steve Sanderson的博客 EmberEmber核心成員中最知名的公眾人物是Yehuda Katz和Tom Dale。 Yehuda Katz是Ember.js、Ruby on Rails和jQuery的核心開(kāi)發(fā)者,他白天的時(shí)間花在他創(chuàng)辦的創(chuàng)業(yè)公司,Tilde Inc.。Yehuda是暢銷(xiāo)書(shū)《jQuery in Action》和《Rails 3 in Action》的作者之一。 Tom Dale原先在SproutCore團(tuán)隊(duì)工作。他以前是蘋(píng)果軟件工程師,在開(kāi)發(fā)MobileMe和iCloud應(yīng)用時(shí)精通了前端JavaScript技能。
圖片來(lái)自Ember Team MeteorMeteor的開(kāi)發(fā)團(tuán)隊(duì)剛剛得到了1.12千萬(wàn)美金,所以他們可以全職開(kāi)發(fā)。他們的團(tuán)隊(duì)有12名開(kāi)發(fā)者,每個(gè)開(kāi)發(fā)者的簡(jiǎn)歷都讓人印象深刻。這個(gè)團(tuán)隊(duì)擁有雄心勃勃的計(jì)劃,超越了大多數(shù)專(zhuān)注于組織客戶(hù)端代碼和狀態(tài)的JavaScript MVC框架。Meteor是一個(gè)全端框架,包括服務(wù)器架構(gòu)和數(shù)據(jù)庫(kù)。 成熟度評(píng)估框架的成熟度可以幫助你理解在項(xiàng)目中使用新技術(shù)的風(fēng)險(xiǎn)。未經(jīng)考驗(yàn)的新框架在文檔、擴(kuò)展性、穩(wěn)定性(API改變)和支持(尋找了解該框架的開(kāi)發(fā)者來(lái)維護(hù)代碼)方面可能存在問(wèn)題,這些問(wèn)題可能導(dǎo)致出乎意料的結(jié)果,即使從其他方面看起來(lái)決策很明智。需要考慮的項(xiàng)目包括:多少生產(chǎn)環(huán)境下的應(yīng)用使用這些框架?這些應(yīng)用有多少用戶(hù)?文檔是否良好?例子和教程是否充足?例子是否過(guò)時(shí)?API是否穩(wěn)定?其他開(kāi)發(fā)者了解或正打算了解這門(mén)技術(shù)么?
大小了解每個(gè)框架的大小,它會(huì)在你的應(yīng)用中增加多少分量是很重要的。大小會(huì)影響性能,不過(guò)它同時(shí)也會(huì)暗示你這個(gè)框架的雄心有多大,你學(xué)習(xí)它可能需要花多少時(shí)間,以及它提供多少幫助你構(gòu)建應(yīng)用的方式(即特性和魯棒性)。一個(gè)框架的野心越大,特性越多,通常也就意味更難在應(yīng)用的頁(yè)面上將它與其他部件組合。輕量的框架更像一個(gè)庫(kù),將他集成到你的項(xiàng)目中所耗費(fèi)的精力也相對(duì)較小。 包括Backbone和Spine在內(nèi)的一些項(xiàng)目為自己的輕量而自豪,這些項(xiàng)目更多地將自己視作庫(kù),而不是框架。通常這些小型的框架留下了空間,你可以使用你自己的庫(kù)來(lái)實(shí)現(xiàn)特定功能,例如模板和路由。我在討論這些框架的特性的時(shí)候?qū)⒗^續(xù)討論這個(gè)話(huà)題。 包括Ember和AngularJS在內(nèi)的其他項(xiàng)目雄心勃勃,更適合叫做框架。它們通常擁有更多內(nèi)建的特性,更少依賴(lài)外部庫(kù)。 下面的列表顯示了我更傾向于將哪些項(xiàng)目歸入庫(kù)或框架:
依賴(lài)性使用這些項(xiàng)目構(gòu)建真實(shí)世界的應(yīng)用的時(shí)候還需要哪些庫(kù)?以下的圖表展示了為了保證開(kāi)發(fā)效率每個(gè)庫(kù)所需的依賴(lài),以及這些依賴(lài)的大小。 通過(guò)從cdnjs下載庫(kù),我們收集了這些數(shù)據(jù)。在實(shí)踐中,大多數(shù)的項(xiàng)目會(huì)使用jQuery配合這些框架處理DOM,因?yàn)樾枰獎(jiǎng)赢?huà)和AJAX。在移動(dòng)應(yīng)用中,使用Zepto.js來(lái)代替jQuery處理DOM不是什么稀奇的事。Zepto.js是一個(gè)比jQuery輕量得多的庫(kù)。雖然Zepto.js不支持Internet Explorer,但是移動(dòng)應(yīng)用通常不需要為此操心。AngularJS包含了一個(gè)jQuery 的縮減版jQLite。但是如果你在項(xiàng)目中使用了jQuery的話(huà),它會(huì)被覆蓋。AngularJS團(tuán)隊(duì)鼓勵(lì)開(kāi)發(fā)者,如非必要,不要添加完整的jQuery庫(kù)。為了幫助你做出正確的選擇,下面的表格同時(shí)顯示了移動(dòng)版(假定使用Zepto.js)和web版(假定使用jQuery)。 互操作性這一部分討論是否框架設(shè)計(jì)為控制整個(gè)頁(yè)面或者它可以被用于現(xiàn)存頁(yè)面的一個(gè)部分——你可能想漸漸將新技術(shù)引入現(xiàn)有的項(xiàng)目。前面的庫(kù)和框架的討論基本可以體現(xiàn)每個(gè)項(xiàng)目的互操作性,庫(kù)更傾向于很容易地集成到現(xiàn)存的項(xiàng)目,而框架為你做更多的事,但是不容易和其他項(xiàng)目配合。 AngularJSAngularJS可以和其他庫(kù)很好地配合,但是它鼓勵(lì)開(kāi)發(fā)者們考慮是否可以不用jQuery和jQueryUI.事實(shí)上Angular內(nèi)置了一個(gè)jQuery的子集jqLite。遵循這一實(shí)踐的理由是讓單元測(cè)試更容易,因?yàn)楹芏嘁蕾?lài)庫(kù)和插件設(shè)計(jì)的時(shí)候沒(méi)有考慮單元測(cè)試,相應(yīng)地更難和單元測(cè)試配合。在實(shí)踐中,大多數(shù)的開(kāi)發(fā)者最終還是因?yàn)槟承┨匦允褂昧薺Query. Backbone由于Backbone的小尺寸和無(wú)預(yù)設(shè)的架構(gòu),將其包含在眾多流行的客戶(hù)端庫(kù)和服務(wù)器端技術(shù)中很容易。 Ember.js被設(shè)計(jì)為在運(yùn)行時(shí)控制整個(gè)頁(yè)面,所以不太適合用于頁(yè)面的部分。 Knockout.js可以在項(xiàng)目中作為小組件使用,不控制整個(gè)頁(yè)面。 啟發(fā)記者采訪(fǎng)音樂(lè)家時(shí)最?lèi)?ài)問(wèn)的問(wèn)題是“你在成長(zhǎng)的時(shí)候聽(tīng)哪些藝術(shù)家的音樂(lè),或者說(shuō),誰(shuí)啟發(fā)了你?”這個(gè)問(wèn)題常常使得讀者能夠預(yù)期音樂(lè)家的聲樂(lè)。這些框架中大部分的觀(guān)念都不是全新的,而是來(lái)自于創(chuàng)造者以前工作的項(xiàng)目中喜歡的部分。這一部分總結(jié)了我從框架創(chuàng)造者的訪(fǎng)談中收集到的關(guān)于啟發(fā)的信息。 AngularJSHTML類(lèi)的聲明性的語(yǔ)言,Adobe和Flex、微軟的WPF\Silverligt等RIA技術(shù)給AngularJS的影響很深。這些聲明性技術(shù)沒(méi)有”主體“方法,僅僅表達(dá)需要發(fā)生什么,而不指定具體實(shí)現(xiàn)。視圖和模型中的數(shù)據(jù)雙向綁定是這一聲明式編程風(fēng)格在絕佳例子。此外,在Google的服務(wù)器端Java代碼中大量使用的依賴(lài)注入和IOC容器(特別是Juice)也啟發(fā)了AngularJS的創(chuàng)造者。他們重視單元測(cè)試,需要框架被設(shè)計(jì)允許依賴(lài)注入,這樣測(cè)試就可以從其他應(yīng)用層剝離出來(lái),運(yùn)行起來(lái)也會(huì)更快。 EmberTom Dale在Quora上談了Ember受到的影響:
此外,Ember.js是SproutCore JavaScript庫(kù)的進(jìn)化版,SproutCore停止仿效Cocoa而更多地借鑒jQuery的時(shí)候,Ember誕生了,理解這一點(diǎn)很重要。 Knockouthanselminutes的播客提供了Steve Sanderson受到哪些方面啟發(fā)的背景信息??偨Y(jié)一下,MVVM設(shè)計(jì)模式和微軟的WPF、Sliverlight等聲明性技術(shù)是最大的啟發(fā)者。你可能會(huì)發(fā)現(xiàn)Knockout的最佳特性——聲明性的數(shù)據(jù)雙向綁定——和Anjular相似,因?yàn)閮烧叩膯l(fā)者是相似的。 理念報(bào)紙?jiān)趫?bào)道新聞的時(shí)候努力保持中立。唯一的例外是編者案,鼓勵(lì)表達(dá)觀(guān)點(diǎn),作者通常在問(wèn)題上占據(jù)一個(gè)強(qiáng)烈的立場(chǎng)。但是大多數(shù)情況,這兩者既不是嚴(yán)格的中立報(bào)道,也不是強(qiáng)烈的意見(jiàn)表達(dá),而是位于兩者之間的連續(xù)統(tǒng)。技術(shù)框架也有類(lèi)似的劃分,即是否強(qiáng)主張。例如,Ruby on Rails推崇約定優(yōu)于配置,并且為開(kāi)發(fā)者做了大量決定,包括文件結(jié)構(gòu)和數(shù)據(jù)訪(fǎng)問(wèn)。相應(yīng)地,它被認(rèn)為是強(qiáng)主張的。其他Sinatra類(lèi)的服務(wù)器端框架更輕量,并不預(yù)設(shè)文件結(jié)構(gòu)和數(shù)據(jù)訪(fǎng)問(wèn)。相應(yīng)的,被看成是無(wú)主張的。服務(wù)端框架有理念,客戶(hù)端JavaScript MVC框架同樣有,我們討論的框架也可以被置于強(qiáng)主張和無(wú)主張的連續(xù)統(tǒng)中考察。讓我們看看每個(gè)項(xiàng)目,然后討論他們的理念。 Backbone: 無(wú)主張Backbone是最開(kāi)明的框架,極度無(wú)主張,允許開(kāi)發(fā)者做出自己的決定,有時(shí)這會(huì)導(dǎo)致代碼差異過(guò)大而難以維護(hù)。唯一的例外是Backbone假定服務(wù)器端有一個(gè)REST服務(wù),我會(huì)在特性部分詳細(xì)討論這一點(diǎn)。這一假定可以通過(guò)覆蓋模型的sync方法來(lái)繞過(guò)。 AngularJS: 強(qiáng)主張AngularJS有較強(qiáng)的主張,特別是它強(qiáng)調(diào)可測(cè)試性和依賴(lài)注入。此外,HTML類(lèi)的聲明性編程很棒的理念也在框架中廣泛體現(xiàn)。 Ember: 極度強(qiáng)主張Ember力求開(kāi)發(fā)者僅對(duì)應(yīng)用的特有部分作決定,其余全部交給約定和支架。這個(gè)理念和Ruby on Rails和jQuery很接近。這一理念最好的表達(dá)出現(xiàn)在的網(wǎng)站上:
Ember標(biāo)準(zhǔn)化了文件和url結(jié)構(gòu),當(dāng)然,有必要的時(shí)候也允許你覆蓋這些設(shè)定。你可以預(yù)期的是大量的代碼會(huì)為你生成,大量的類(lèi)似文件結(jié)構(gòu)的約定。相應(yīng)地,你需要做出的常規(guī)選擇更少,因?yàn)榭蚣芤呀?jīng)為你選定了合理的默認(rèn)值,你可以著手構(gòu)建你的應(yīng)用的特殊部分。 Knockout: 無(wú)主張路由和數(shù)據(jù)存儲(chǔ)留給開(kāi)發(fā)者決定。不預(yù)設(shè)文件或URL結(jié)構(gòu)。甚至允許用基于字符串的模板替換聲明性的基于DOM的模板。 特性我們可以將這些JavaScript MVC框架看成是幫助開(kāi)發(fā)者構(gòu)建單頁(yè)應(yīng)用的常用特性集合。每個(gè)框架實(shí)現(xiàn)這些特性的方式,或者不實(shí)現(xiàn)這些特性的方式(通過(guò)其他庫(kù)來(lái)補(bǔ)全框架的功能)是值得留心的。 JavaScript MVC框架的主要特性是什么?
除此以外,一些框架提供常用的語(yǔ)言層面的服務(wù),例如通用的pub/sub事件模型和面向?qū)ο蟮睦^承支持。 數(shù)據(jù)綁定這是最受吹捧的特性。你通過(guò)HTML input修改了數(shù)據(jù),綁定到input的JavaScript對(duì)象馬上更新,其他綁定的用戶(hù)接口元素也隨之更新。在很多框架中,反之亦然。如果你修改了JavaScript對(duì)象,html會(huì)自動(dòng)刷新。這是一個(gè)web上的雙向的數(shù)據(jù)綁定,我們?cè)贔lex、Windows Forms、WPF等富客戶(hù)端應(yīng)用框架中見(jiàn)過(guò)這類(lèi)綁定。以下的表格顯示了哪些框架支持?jǐn)?shù)據(jù)綁定。 有些人可能持有異議,因?yàn)锽ackbone和Spine部分支持?jǐn)?shù)據(jù)綁定。但是我覺(jué)得大量工作需要留給開(kāi)發(fā)者,保險(xiǎn)起見(jiàn),不如說(shuō)這些庫(kù)不支持這些特性。 視圖模板客戶(hù)端的JavaScript數(shù)據(jù)模型需要穿插在HTML中,這些框架采用兩種方式解決問(wèn)題。 基于字符串的模板(目前最流行的是handlebars.js),將字符串、文本模板中的動(dòng)態(tài)部分替換為模型中的數(shù)據(jù)。字符串常被提到也飽受爭(zhēng)議的特性之一是性能。其缺點(diǎn)是調(diào)試控制語(yǔ)句類(lèi)的邏輯很困難。 基于DOM的模板擁抱標(biāo)記語(yǔ)言的聲明式本性,這是開(kāi)了掛的html,通過(guò)html中的附加屬性來(lái)描述需要的綁定和事件。這些庫(kù)需要的代碼大大減少,為開(kāi)發(fā)者做了很多事情。 模型(可觀(guān)察的:跟蹤改動(dòng))一些框架(Backbone、Spine)更專(zhuān)注于模型,要求開(kāi)發(fā)者在base模型的基礎(chǔ)上擴(kuò)展JavaScript類(lèi),通過(guò) 其他庫(kù)(AngularJS)對(duì)頁(yè)面上的所有綁定的DOM元素作臟檢查,因?yàn)闆](méi)有標(biāo)準(zhǔn)的get和set訪(fǎng)問(wèn)器。因此將這些庫(kù)用于大頁(yè)面時(shí)將導(dǎo)致性能問(wèn)題。這些庫(kù)不僅需要更少的刷新模板的代碼,也不需要你使用特定的get和set訪(fǎng)問(wèn)器來(lái)修改模型中的數(shù)據(jù),所以你可以使用原始的JavaScript對(duì)象。這大大提升了開(kāi)發(fā)效率,這一點(diǎn)在框架的初學(xué)者身上體現(xiàn)得尤為明顯。 數(shù)據(jù)存儲(chǔ)這些框架通過(guò)以下方式將數(shù)據(jù)存儲(chǔ)到服務(wù)器
REST一些框架默認(rèn)預(yù)設(shè)后端有非常整潔的REST JSON服務(wù),并且,至少在默認(rèn)的情況下,前端與后端頻繁交互,在后臺(tái)異步更新數(shù)據(jù),而用戶(hù)界面響應(yīng)流暢。這些框架內(nèi)部使用jQuery或Zepto發(fā)送合適的AJAX請(qǐng)求給服務(wù)器。用戶(hù)界面的HTML DOM元素監(jiān)聽(tīng)?wèi)?yīng)用的JavaScript對(duì)象模型的改動(dòng),同步機(jī)制得到模型屬性的更改提醒,將改動(dòng)發(fā)送給REST服務(wù),確保模型和服務(wù)器同步。 在線(xiàn)和離線(xiàn)Backbone默認(rèn)在客戶(hù)端保存數(shù)據(jù)之前發(fā)送請(qǐng)求,這樣服務(wù)器端和客戶(hù)端同步就很容易。和Backbone非常類(lèi)似的Spine框架,采用了不同的方式,在異步發(fā)送請(qǐng)求到服務(wù)器前,先在客戶(hù)端存儲(chǔ)記錄,這提供了更好的用戶(hù)界面響應(yīng),在移動(dòng)應(yīng)用中常發(fā)生的離線(xiàn)狀態(tài)下也能工作。如果你的項(xiàng)目需要支持離線(xiàn),需要了解清楚框架對(duì)該特性的支持 DIY這些框架要求開(kāi)發(fā)者使用 數(shù)據(jù)存儲(chǔ)特性Meteor之類(lèi)精心制作的框架擁有更完整的數(shù)據(jù)存儲(chǔ)方案,但是要求服務(wù)器端有MongoDB數(shù)據(jù)庫(kù)。這類(lèi)方案試圖提供一個(gè)擴(kuò)展性?xún)?yōu)異的默認(rèn)解決方案,提供從頭到尾的JavaScript開(kāi)發(fā)體驗(yàn)。 以下的表格總結(jié)了每個(gè)框架是如何處理數(shù)據(jù)存儲(chǔ)的。 路由將URL路由映射到JavaScript函數(shù),可以支持瀏覽器的后退按鈕。單頁(yè)應(yīng)用最大的缺點(diǎn)之一是由于頁(yè)面無(wú)刷新,瀏覽器歷史不會(huì)添加條目,所以后退按鈕通常無(wú)法將用戶(hù)帶回頁(yè)面的前一狀態(tài),除非開(kāi)發(fā)者在主要的狀態(tài)改變時(shí)做一些額外的工作,通過(guò)在URL后附加井號(hào),或者,使用現(xiàn)代瀏覽器的push和pop狀態(tài),實(shí)現(xiàn)狀態(tài)跟蹤機(jī)制??傊?,大多數(shù)項(xiàng)目都提供基本、初步而有用的功能。Knockout的做法很簡(jiǎn)單,允許你使用其他的第三方開(kāi)源庫(kù)。 蘋(píng)果對(duì)蘋(píng)果考察各個(gè)框架的特性之后,我發(fā)現(xiàn)我并不是在做一個(gè)“蘋(píng)果對(duì)蘋(píng)果”的比較。一個(gè)更為公平的比較也許是將AngularJS和EmberJS之類(lèi)全面的框架與配合第三方庫(kù)使用的Backbone和KnockoutJS之類(lèi)的MV*框架進(jìn)行比較。具體來(lái)說(shuō),下面的比較會(huì)更有意義:
以后的博客中我會(huì)繼續(xù)深入。 告訴我更多為項(xiàng)目選擇JavaScript MVC框架時(shí)有大量需要考慮的事項(xiàng),我希望本文是一個(gè)良好的開(kāi)始。請(qǐng)?jiān)谠u(píng)論中分享你使用這些框架的體驗(yàn),包括它們的優(yōu)異之處,也包括它們使用上的陷阱。 |
|
來(lái)自: ThinkTank_引擎 > 《MVC》