AngularJS 、Backbone.js 和 Ember.js 的比較

jopen 10年前發布 | 38K 次閱讀 Backbone.js angularjs

1 介紹

我們準備在這篇文章中比較三款流行于Web的“模型-視圖-*”框架:AngularJS、Backbone和Ember。為你的項目選擇正確的框架能夠對你及時交付項目的能力和在以后維護你自己代碼的能力產生巨大影響。你也許想基于一款可靠的、穩定的和成熟的框架來構建項目,但又不想為此受到約束。Web發展迅速——新技術產生,舊的那套方法很快跟不上潮流。如此形勢之下,我們準備仔細深入的比較這三個框架。

2  框架概覽

今天我們提到的所有框架有許多共同點:都是開源的,遵從 MIT 協議,并且都嘗試通過 MV* 模式來解決開發單頁面應用的問題。它們都有類似的概念:視圖,事件,數據模型和路由。我們先簡單回顧一下有關的歷史和背景知識,然后再展開深入比較這三款框架。

AngularJS 誕生于 2009 年,當時作為一個大型商業產品的一部分叫做 GetAngular。不久之后,Misko Hevery,GetAngular 項目創建者之一,花了僅僅三周時間,用 GetAngular 重寫了一個曾經耗時 6 個月才完成的,有 17K 行代碼的頁面應用,并將代碼削減到 1,000 行左右,于是成功的說服了谷歌開始贊助該項目,并將其開源,也就是我們今天看到 AngularJS 。Angular 的特點是擁有雙向數據綁定,依賴注入,易于測試的編碼風格,以及通過使用自定義指令可以簡單的擴展 HTML。

Backbone.js 是一個輕量級的 MVC 框架。誕生于 2010 年,它作為那種笨重全功能的 MVC 框架,比如說 ExtJS, 的一個代替品,迅速流行開來。 很多服務都使用了它,比如 Pinterest, Flixster, AirBNB 等等。

Ember 則要回溯到 2007 年,最開始是以 SproutCore MVC 框架展現在世人面前,由 SproutIt 開發,后來是 Apple,再后來到 2011 的時候,jQuery 和 Ruby on Rails 的核心貢獻者 Yehuda Katz 參與了進來。有名的 Ember 用戶包括了 Yahoo!, Groupon, 和 ZenDesk。

3 社區

社區是在選擇一個框架的時候,要考慮的最重要因素之一。大社區意味著更多的答案,更多的第三方模塊,更多的 油Tube 教程…你,明白了么。我做了個統計,截止 2014年8月16日,Angular 是絕對的王者,作為 GitHub 上第六大星級項目,在 StackOverflow 上的提問比 Ember 和 Backbone 加起來還多,你自己看:

</tr>

</tbody>

指標 AngularJS Backbone.js Ember.js
Github 的點贊星數 27.2k 18.8k 11k
第三方模塊 800 ngmodules 236 backplugs 21 emberaddons
棧爆網的提問件數 49.5k 15.9k 11.2k
油Tube 件數 ~75k ~16k ~6k
GitHub 貢獻者 928 230 393
Chrome 插件用戶 150k 7k 38.3k

所有這些指標,顯示的僅僅是每個框架的當前狀態。看看哪個框架增長最快也是很有趣的,你有福了,通過谷人希的趨勢跟蹤,你可以得到以下答案:

http://www.google.com/trends/explore?hl=en-US#q=ember.js,+angularjs,+backbone.js&cmpt=q

4 框架大小

頁面的加載時間是你網站成功的關鍵。當涉及瀏覽速度的時候,用戶沒太多耐性 — 所以很多情況下你要盡可能讓你的應用跑得越快越好。使用框架,有兩個因素會對應用的加載時間產生影響: 框架的大小和它啟動的時間。

Javascript 資源通常都會被經過精簡和壓縮,所以我們來比較一下壓縮版。但是只看框架的大小肯定不夠的。Backbone.js,盡管是最小的 (只有 6.5kb),但是必須 Underscore.js (5kb) 和 jQuery (32kb) 或者 Zepto (9.1kb),而且你還有可能還有一些第三方插件要加進來。

</tr>

</tbody> </table>

5 模板

Angular 和 Ember 都有模板引擎。而另一方面 Backbone,把這個選擇權留給了你。感受模板引擎的異同最好的辦法就是上點代碼,好的,我們開始。我們將演示把一個列表轉換成 HTML 列表的例子。

5.1 AngularJS

Angular 的模板引擎僅僅是在 HTML 上使用綁定表達式。而綁定表達式又僅僅是兩層大括號而已:

<ul>
  <li ng-repeat="framework in frameworks" 
      title="{{framework.description}}">
    {{framework.name}}
  </li>
</ul>

5.2 Backbone.js

Backbone 可以和許多第三方模板引擎集成,默認的選擇是 Underscore 模板。 因為 Underscore 是 Backbone 的依賴項,你已經把它加載到頁面中了,你無須添加任何額外的依賴關系就可以使用它的模板引擎。不爽的是,Underscore 的模板引擎非常初級,你通常不得不把 javascript 混進去,比如說:

<ul>
  <% _.each(frameworks, function(framework) { %>
    <li title="<%- framework.description %>">
      <%- framework.name %>
    </li>
  <% }); %>
</ul>

5.3 Ember.js

Ember 目前用的是 Handlebars 模板引擎,熱門的 Mustache 模板引擎的擴展。一個新的 Handlebars 變種,叫做 HTMLBars ,目前已經可以使用了。Handlebars 不關心 DOM – 它所做的僅僅是做一個簡單的字符串變換。而 HTMLBars 則可以處理 DOM,所有的變量轉換都有上下文感知。由于 HTMLBars 還沒有流行,我們還是來看看用 Handlebars 方式打印列表方式:

<ul>
  {{#each frameworks}}
    <li {{bind-attr title=description}}>
      {{name}}
    </li>
  {{/each}}
</ul>

6 AngularJS

6.1 好處

Angular 為 Web 開發帶來了許多創新的概念。雙向數據綁定節省了大量的樣板代碼。比如下面的 jQuery 代碼片段:

$('#greet-form input.user-name').on('value', function() {
    $('#greet-form div.user-name').text('Hello ' + this.val() + '!');
});

由于 Angular 的雙向綁定,你根本就不需要自己寫代碼。只需要在 HTML 模板里面聲明綁定就可以了:

<input ng-model="user.name" type="text" />
Hello {{user.name}}!

Promises 在 Angular 中扮演了一個重要的角色。Javascript 是單線程,基于事件循環的語言,這意味著許多操作(比如說網絡通訊)都是以異步方式進行的。異步的 Javascript 代碼會很快的就陷入了長長的嵌套回調,也就是臭名昭著的 “Pyramid Code” 或者叫做 “Callback Hell”。

相對比另外兩個,Angular 不光有著更大的社區,更多的在線文檔,而且還有谷歌在背后的推廣和支持。所以,核心團隊還在不斷增長,產出更多的創新,以及改善開發生產效率的工具,比如: Protractor, Batarang, ngmin 和 Zone.js,一抓一大把。而且,開發團隊還向用戶征集需求。比如說,Angular 2.0 的所有設計文檔你都可以從 這里 找到,任何人都可以直接給設計文檔提建議。

Angular 幫助你把構建應用的程序塊劃分為下面這幾種類型:控制器(Controller),指令(Directive),工廠(Factory),過濾器(Filter),服務(Service)和視圖(View) (就是模板)。它們被組織為模塊形式,之后可以被另一個引用。每種類型有不同的作用。視圖處理 UI,控制器處理 UI 背后的邏輯,服務用來處理和后臺的通信,并且將共通的有關聯的功能組件結合在一起,而指令通過定義新的元素,屬性和行為,很容易的構造可重用的組件,以及HTML擴展。

自動臟值檢查意味著,你不需要用 getter 和 setter 去訪問數據模型 — 你可以修改任意范圍(scope)的任意屬性,然后 angular 會自動檢測到變化,通知該屬性的所有觀察者(watcher)。

“Angular 的初衷是寫出可測試的代碼。” 單元測試指南中的這句話,包含了太多意思 – Angular 確實很注重分離,單元隔離,為 $http 和 $timeout 等基礎內置服務提供了現成的,強大的 mock。

6.2 痛處

Angular 常被人詬病的是指令那復雜的 API。 Transclusion,尤為突出,這個概念,把許多開發者搞得一頭霧水,讓你滿腦子各種概念,比如編譯函數(compiling function),linking,函數的預處理/后處理(pre/post linking functions),各種 scope 類型 (transclusion/isolate/child scope),還有各種配置設置,需要相當的時間來掌握。

Angular 中的 scope 層次結構使用的是 Prototypal 繼承,這又是一個為了迎合從面向對象語言,比如 Java 和 C#,過來的開發人員而提出的概念。不理解 scope 導致許多開發者開發很受傷 (比如說: , 還有)。

Angular 表達式 在視圖層被廣泛應用。表達式語言非常強大,有時候是強大過頭了。這誘導開發者使用各種復雜的邏輯,甚至執行賦值運算和計算全部都放在模板中。把邏輯運算放在模板中讓它非常難以測試,因為它變成不可能獨立測試了。看看下面的例子,演示了如何濫用這種模板語言的:

<button ng-click="(oldPassword && checkComplexity(newPassword) && oldPassword != newPassword) ? (changePassword(oldPassword, newPassword) && (oldPassword=(newPassword=''))) : (errorMessage='Please input a new password matching the following requirements: ' + passwordRequirements)">Click me</button>

許多情況下,指令名稱的拼寫錯誤,或者調用未定義 scope 方法,都會被忽略,并且很難被發現,特別是當你把復雜的指令 API 和上面提到的 scope 的繼承弄到一起的時候。我見過有些苦逼花費一大堆時間抓耳撓腮想找出為什么 scope 中的一個綁定的事件沒被回調函數觸發,最后居然是因為用了駝峰(camelCase)命名,而沒有用連字符分隔(hyphen-separated)拼寫屬性的名稱(比如說).

最后,是 Angular 的循環系統中, 要注意那“神奇的”臟值檢查,它經常會給開發者驚喜。在非-Angular上下文運行的時候,很容易忘記調用 $digest() (例子)。也就是說,你必須非常小心,不要觸發緩慢的觀察者事件或者無限循環(例子: , 還有 )。通常,對于一頁上有大量的交互元素的頁面,Angular會變得非常慢。有個很好的界定是,不要在同一頁面上放超過 2,000 個活動的綁定。

7 Backbone.js

7.1 好處

Backbone 輕量,快速,內存占用小。學習曲線也是很平緩的,只需要幾個簡單的概念就能掌握 (模型/集合, 視圖, 路由)。它有很棒的文檔,代碼簡單,注釋詳細,并且這里還有一個注釋版源碼,用來解釋框架的工作細節。實際上你可以通讀整個框架的源碼,用不到一個小時去熟悉它。

因為又小又基礎,你可以基于 Backbone 打造你自己的框架。一些基于 Backbone 的第三方框架的例子有 Aura, Backbone UI, Chaplin, Geppetto, Marionette, LayoutManager, Thorax, Vertebrae。用 Angular 和 Ember 你一般都要用框架作者給你的選擇,有些可能會不適合你的工程需求和個人風格。Angular 2.0 承諾改變這種情況,通過構建更小的獨立模塊,使你可以選擇和組合它們。不過我們還沒看到它什么時候才能交付。

7.2 痛處

Backbone 沒有提供基本構造。它僅僅是提供了一些基礎工具讓你去創建,讓你去決定如何構造應用,這有太多空要填了。比如說內存管理需要小心的處理。由于缺失視圖生命周期管理,這會使得路由/狀態的變化,很容易導致內存泄漏,除非你可以很清楚的處理一切。

誠然,Backbone本身不提供的功能,可以由第三方插件來填補,這也就意味著,在你創建應用的時候,有很多選擇,因為一個功能通常有許多個備選插件。比如說,內嵌模型可以由下面這些插件提供:Backbone.DocumentModel, BackBone.NestedTypes, Backbone.Schema, Backbone-Nested, backbone-nestify, 這還是其中的一小部分。決定哪個更適合你的工程是需要調查的,這需要時間 — 而使用框架的一個主要目的是節省你的時間。

Backbone 缺乏對雙向數據綁定的支持,意思也就是說,你必須編寫大量的樣板來處理模型更新之后觸發的視圖更新。看看上面給出的例子,想想看 Angular.js 的雙向數據綁定削減了多少樣板代碼。

Backbone 中的視圖是直接操作 DOM 的,這讓它們非常難做單元測試,也就更脆弱,更難以重用。常見的例子就是用 CSS 選擇器查找 DOM 元素,改變CSS 類名,添加有同樣類名的新元素或者把同樣的 DOM 樹包裝到另一個元素,都會打亂你的 CSS 選擇器以及應用的渲染。

8 Ember.js

8.1 好處

Ember.js 主張約定優于配置。也就是說,無需編寫大量的樣板代碼,Ember 會自動推導出許多配置本身,比如在定義一個路由資源的時候,可以自動判定路由的名稱和控制器。Ember 甚至會在你沒定義控制器的時候,自動為你的資源生成一個。

Ember 包含了一個優秀的路由和一個可選的數據層,叫做 ember data。和其他兩個框架不同,它們的數據層非常小(Backbone 的集合/模型和 Angular 的 $resource),Ember 有一個拿來即用的非常成熟的數據模塊,只需要簡單的配置,就可以和后臺的 Ruby-on-Rails 或者其它的 RESTful JSON API 集成得非常好。它還可以通過設置 fixtures來支持面向 mock API 開發以及測試。

性能是 Ember.js 設計的主要目標。諸如 The Run Loop 這個概念,可以確保數據的變化只導致單個 DOM 更新,即使同一塊數據進行了多次更新也是一樣,還有計算屬性的緩存, 還有可以在編譯時或在服務端對 HandleBars 模板進行預編譯的能力,都可以幫助你保證應用的負載,保證它跑得足夠快。

8.2 痛處

Ember 的 API 在它穩定版出來之前變化太大了。這導致了有大量的過期內容和不能再運行的例子,這會新進開發者開始使用這個框架時感到非常困惑。看看 Ember Data 變更日志,你就會知道我說的是什么意思了。這里有太多的大變更了,這就讓許多棧爆網的回答和編碼例子變得毫無意義了(比如說這)

Handlebars 為了保持模板和數據模型一致,用了太多的 <script> 標簽來污染 DOM 了。這會在遷移到 HTMLBars 的時候變得毫無意義,但到那時,你的 DOM 樹上全都是 <script> 標簽,會幾乎無法辨認哪些是你的代碼了。還有最糟糕的部分 – 這會打亂你的CSS樣式,或者影響和其他框架的集成,比如說 jQuery UI 的排序

9 總結

我們已經看過三個框架的長處短處。Ember 的綜合能力,其中的 MVC 結構,對于那些曾經在 Ruby, Python, Java, C# 或者其他面向對象語言中有過 MVC 編程背景知識的程序員來說非常有意義。Ember 還帶來了媲美桌面應用的性能,而且還因為約定優于配置的原因,可以讓你節省非常多樣板代碼。

Backbone 崇尚極簡主義。它夠小,夠快,夠簡單,但是提供了你構建應用所需要的最小集(許多情況下,甚至要小于最小集)。

Angular 的擴展 HTML 的創新方法,對于骨子里是 web 開發者的人來說非常有意義。它有強大的社區,有谷歌在后面支持它,它不斷沉淀和成長。它不但適用于快速原型開發,還適用于大型生產應用。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!
框架     凈大小      包含依賴之后的大小
AngularJS 1.2.22      39.5kb      39.5kb
Backbone.js 1.1.2      6.5kb      43.5kb (jQuery + Underscore)
     20.6kb (Zepto + Underscore)
Ember.js 1.6.1      90kb     136.2kb (jQuery + Handlebars)