AngularJS 1.2.22 |
39.5kb | 39.5kb | </tr>
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) |
</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 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!
sesese色