Angular 2 VS. React: 血色將至
原文連結:https://medium.com/@housecor/angular-2-versus-react-there-will-be-blood-66595faafd51#.g1eaz7lye
轉發來自:http://www.zcfy.cc/article/142
Angular2 已升級到 Beta 版並有可能成為 2016 年最火的新框架。尖峰時刻到了,讓我們看看它如何應對 2015 年新寵 React。
宣告:我很享受在 Angular 1 的工作,但是我已在 2015 年轉到了 React。我剛剛釋出了一個免費試用課程“多視角解讀 React 和 Flux”。是的,我有些偏心,但這兩者的缺點我都會指出。
Photo credit: @jwcarrol
比較蘋果和猩猩
是的, Angular 是一個框架,React 是一個庫。有些人說比較他們的區別是毫無意義的。胡說!
在 Angular 和 React 之間做選擇就像選擇買一個現成的電腦與選擇利用現成的部件組裝你自己的電腦。
本博文會涉及到這兩個方法的優點。我將 React 的語法和元件模型與 Angular 的語法和元件模型進行對比,這就像對比一個現成的電腦的 CPU 與一個半成品的 CPU。
Angular 2 優勢
我們先研究 Angular 2 相比 React 的優勢。
少一些選擇疲勞
因為 Angular 是一個框架,它提供了非常多好用的思想與功能。而 React,你通常需要加入許多現成的庫才能構建一個真正的應用。你可能想要一個路由庫、執行單向流庫、web API 呼叫庫、測試庫、依賴管理庫等等。一大堆的選擇令人不知所措。這就是為什麼 React 有這麼多入門套件的原因(我就已經釋出了兩個)。
Angular提供了更多現成的思路,可以幫助你快速入門而不用為選擇庫感到恐懼。這種強制一致性也幫助新員工快速入門並使得開發者在團隊之間的切換更高效。
我很欣賞 Angular 核心團隊已經擁抱 TypeScript,這引出了下一個優點……
TypeScript = 坦途一條
當然, 不是所有的人都喜歡 TypeScript,但是 Angular 2 執著地使用這種 JavaScript 風格是好事。React 的例子在網上非常的不統一 —— 使用 ES5 和 ES6 的數量大約是相等的,而現在又提供了三種不同的方式來宣告元件。這給新人帶來了困惑。(Angular 也使用 decorator 替代 extend —— 許多人認為這是有好處的)。
雖然 Angular 2 不要求使用 TypeScript,但 Angular 核心團隊毫無疑問地擁抱它並在文件中預設使用它。這意味著相關的例子以及開源專案可能讓你感到更熟悉和一致。Angular 已提供了清晰的例子來說明如何使用 TypeScript 編譯器。(雖然不可否認的是,不是每個人都已接受了 TypeScript,但我猜想在它釋出後不久就會成為現實標準)。這種一致性,可以避免使用 React 帶來的過多的困惑和爭論。
少一些折騰
2015 是 JavaScript 疲勞 的一年。React 是一個關鍵的貢獻者。因為 React 1.0 版本還未釋出,未來可能會有重大修改。React 的生態系統也在快速發展,尤其是圍繞著眾多 Flux 特性和路由。這意味著,你現在使用 React 寫的東西,在 React 1.0 正式釋出後,會覺得過時或需要大改版。
相反, Angular 2 是一個謹慎的、全面的、成熟的系統再造。所以 Angular 在釋出後不用大動干戈地改來改去。並且作為一個全面的框架,當你選擇了 Angular,你可以信任一個獨立的團隊對未來做出的謹慎的決定。使用React,你需要照管一大堆不相干又快速變化的開源庫,要確保它們在一塊可以順利協作。這是一項費時的、有挫敗感的並且永不止步的工作。
大量的工具支援
正如你接下來看到的,我認為 React 的 JSX 是不錯。但是,你需要選擇工具來支援 JSX。React 已經如此流行了,因此現在工具的支援不是大問題,但像 IDE 和 linter 這樣的新工具並沒有支援 JSX。Angular 2 的模板使用一個字串或分開的 HTML 檔案來儲存標籤,因此它不需要特殊的工具支援(儘管它釋出了工具來智慧地解析 Angular 的字串模板)。那就是說,Angular 的方法有它自身的缺陷,這有利於繼續討論 React 的優勢……
React 優勢
JSX
JSX 是 HTML 類似的語法並能編譯成 JavaScript。標籤和程式碼放在同一檔案。這意味著程式碼自動補全幫助鍵入你引用的元件的函式和變數。相反,Angular 的基於字串的模板帶來常見的缺點:許多編輯器沒有程式碼顏色區分、有限的程式碼補全支援、run-time 失效。通常這時候你會想到出錯訊息是不是也不行啊,但是 Angular 團隊建立了他們自己的 HTML 解析器來修復那個問題(太棒了!)。
如果你不喜歡 Angular 基於字串的模板,你可以把模板挪到獨立的檔案中,但是沒有程式碼補全的支援與編譯時校驗的幫助,你需要同時記住兩個檔案,並在兩個檔案中切換。然而當你愉快地使用 React 時,這些都不是事兒。JSX 之所以如此特別,就是因為元件是由單個編譯時校驗的檔案組成。
對比 Angular 2 與 React 是如何處理缺少閉合標籤的。
想了解為什麼 JSX 如此牛逼,請看這 JSX: The Other Side of the Coin。
React 報錯精準迅速
當你在 React JSX 中寫了一個錯字,JSX 就不會被編譯。這是件好事。這意味著你能立刻正確地知道哪行出錯了。當你忘記寫閉合標籤或你引用了一個不存在的屬性時,它會立即通知你。實際上,JSX 編譯器會標明錯誤出現的行號。這個行為從根本上加快了開發速度。
相反,當你在 Angular 2 中寫錯了變數引用,什麼也不會發生。 Angular 2 會在執行的時候悄悄地報錯,而不是編譯時報錯。它的報錯很慢,我載入了應用卻不知道為什麼沒有展示我的資料,很不爽。
React 以 JavaScript 為中心
這是 React 和 Angular 之間的本質區別。不幸的是, Angular 2 依然保留以 HTML 為中心而不是以 JavaScript 為中心。Angular 2 沒有解決它本質的設計問題:
Angular 2 將 “JS” 嵌入 HTML。React 將 “HTML” 嵌入 JS。
這種背道而馳的設計思路影響太大了,它從根本上影響著開發體驗。 Angular 以 HTML 為中心的設計保持著它最大的弱點。正如我在 “JSX: The Other Side of the Coin”說的,JavaScript 比 HTML 更強悍。因此,強化 JavaScript 來支援標籤比強調 HTML 來支援邏輯更可行。React 設法將 HTML 和 JavaScript 粘合在一起, React 的以 JavaScript 為中心方式從根本上優於 Angular、Ember 以及 Knockout 的以 HTML 為中心方式。
React 以 JavaScript 為中心的設計 = 簡單
Angular 2 沿用了 Angular 1 試圖讓 HTML 更強大的方式。所以你必須為迴圈或條件分支等簡單的任務使用 Angular 2 的獨特語法。例如,Angular 2 通過兩種語法提供了單向和雙向資料繫結,不幸的是,這兩種方式十分不同:
{{myVar}} //One-way binding
ngModel="myVar" //Two-way binding
在 React 裡,繫結標籤不會根據這種決定而改變(它是在其他地方被處理,我同意它應該是這樣)。在任何情況下,它看起來是這樣的:
{myVar}
使用這種語法,Angular 2 支援內聯主模板:
<ul>
<li *ngFor="#hero of heroes"
{{hero.name}}
</li>
</ul>
上面的程式碼片段是 heros
陣列的遍歷。我有幾個問題:
- 通過一個程式星號來宣告一個“主模板”是晦澀的。
hero
前面加 # 是宣告一個本地模板變數。這個關鍵的概念看起來是不需要的雞肋(如果想加,你可使用var
)。- 通過一個 Angular 式宣告的屬性
ngFor
為 HTML 新增迴圈的語義。
相比上面 Angular 2 的語法,React 的語法是純粹的 JS:
<ul>
{ heroes.map(hero =>
<li>{hero.name}</li>
)};
</ul>
因為 JS 原生支援迴圈,React 的 JSX 可以簡單地利用所有的 JS 能力來處理這些事,並使用 map、filter 等做更多的事。
讀一下 Angular 2 Cheat Sheet。那不是 HTML,也不是 JavaScript。它是 Angular。
為了閱讀 Angular:需要學習一長串 Angular 式宣告的語法。 為了閱讀 React:只需要學習 JavaScript。
React 因它的語法和概念簡單而獨特。細想當下流行的框架或庫的迭代迴圈:
Ember: {{# each}}
Angular 1: ng-repeat
Angular 2: ngFor
Knockout: data-bind=”foreach”
React: JUST USE JS. :)
除了 React,其它框架都重新發明了JavaScript中本來就有而且非常簡單的迴圈。這就是 React 的美妙之處,它利用 JavaScript 的能力來處理標籤,所以不需要新的奇怪的語法。
Angular 2 奇怪的語法也沿用在 click
繫結:
(click)=”onSelect(hero)"
相反,React 再一次使用了普通的 JavaScript 語法:
onClick={this.onSelect.bind(this, hero)}
因為 React 包含了一個綜合事件系統(Angular 2 也有),因此你不必擔心像這樣內聯宣告的事件處理的效能影響。
奢華的開發體驗
JSX 的程式碼補全支援、編譯時校驗以及豐富的錯誤訊息已經建立了非常棒的開發體驗,並能減少輸入節省時間。
大小問題
這有幾個值得關注的框架或庫壓縮之後的大小:
Ember: 580k
Angular 2: 565k (759k with RxJS)
Angular 1: 324k
React + Redux: 204k
為了做一個真實的比較,我分別使用 Angular 2 和 React 來搭建 “Angular 2’s Tour of Heroes” 應用(我使用新的 React Slingshot 初學者工具包)。結果是?
Angular 2: 764k 壓縮後
React + Redux: 216k 壓縮後
因此簡單比較後,Angular 2 的應用大小比 React + Redux 的應用要大 3 倍多。
我承認關於框架尺寸的擔憂可能被誇大了:
大型應用很容易達到幾百 K 的程式碼底線,不管它們是否使用了框架構建,結果往往會超過這個底線。開發者為了構建複雜的軟體需要將其抽象化,無論這些抽象化來自框架還是手寫,都會對應用造成負面影響。
即使你完全去掉框架,許多應用仍然後幾百 K 的 JavaScript。—— 摘自 Tom 的 JavaScript Frameworks and Mobile Performance。
Tom 的觀點是對的。像 Angular 和 Ember 這樣的框架是很大的,因為他們提供了應用之外的功能。
但是,我的疑問是:許多應用不需要將這些大框架全部放在裡面。換句話說,越來越多的人擁抱微型服務、微型應用以及單獨維護的程式包,React 讓你可以根據你選擇的必需的功能來限制你的應用大小。在一個有著 200,000 個 npm 模組的世界裡,這絕對是強大的地方。
React 信奉 Unix 哲學.
React 是一個庫。它恰恰是與那些大型的、全面的框架如 Angular 和 Ember 的思想相反。那麼當你選擇了 React,你可以自由選擇當下最好的庫來最優地解決你的問題。JavaScript 發展很快,而 React 允許你用更好的庫來替換你的應用程式的區域性,而不是等待和期盼你的框架做創新。
Unix 已接受住了時間的考驗,原因是:
擁有小、可組裝性、目的單一的思想的工具永遠不會落伍。
React 作為焦點集中、可組裝以及目的單一的工具被用在世界上許多大型的網站。這預示著它的未來前途光明(那就是說,Angular 也被用於許多大牌網站)。
對比彙總
Angular 2 相比版本 1 有很大的改進。新的元件模型比 V1 的指令容易掌握,它支援同構或萬能的渲染,並且它使用了 virtual DOM 提供了 3-10 倍的效能提升。這些改進使得 Angular 2 同 React 非常具有競爭力。不可否認的是,它的功能齊全、執著的天性提供了一些明顯的好處,減少了 “JavaScript 疲勞”。
但是,Angular 2 的大小和語法讓我猶豫。Angular 致力於以 HTML 為中心,相對於以簡單的 JavaScript 為中心模型的 React,Angular 更復雜。使用 React,你不需要學習框架的宣告 HTML 語法例如 ngxxx。
Cory House 是“使用 React 和 Flux 構建應用程式”、 “Clean Code: Writing Code for Humans” 的作者,並在 Pluralsight 上釋出了許多其他的課程。他是 VinSolutions 的軟體架構師,並在全球培訓軟體開發者,像前端開發以及整理程式碼等軟體實踐等內容。Cory 是一名 Microsoft MVP,Telerik 開發專家,outlierdeveloper.com 創始人。