幾年前,當我寫的程式碼被各種各樣的jQuery選擇器和回撥函式搞得亂七八糟的時候,AngularJS把我從中解救了出來。
Angular幫助我改善了開發專案的可維護性,而且提供了很多觸手可得的功能,它是為建立大型web應用而生的工具,極大方便了快速開發大型應用。
我還記得AngularJS的雙向資料繫結和模型是唯一資料來源的哲學是怎樣得讓我驚歎,事實上,他們大大減少了我編寫的應用的程式碼冗餘。
隨著時間的推移,我發現了Angular的一些弊病,最終,我對這些缺點失望至極,於是開始尋找它的替代品。
下面這些是我對Angular的憂慮。
基於DOM執行。Angular的執行流程嚴重依賴DOM, Angular應用在預設的引導過程中會掃描DOM並按DOM中指令的優先順序將模板編譯,這樣讓除錯和檢測執行順序變得困難。
雙向資料繫結是一把雙刃劍。隨著你的元件變得複雜,這種方式可能導致效能問題。
雙向繫結是如何影響到效能的呢?
JavaScript (ES5)沒有實現任何通知變數和物件發生變化的方法,因此Angular使用一種叫做“髒檢查“的機制來跟蹤資料變化並同步使用者介面。
任何Angular作用域內的操作都會觸發髒檢查,導致了隨著繫結增多應用效能會降低。
雙向繫結的另一個問題是,頁面上許多元件能夠改變資料,也就意味著有很多資料的輸入來源,如果不能很好管理的話,會導致混亂和難以應對的局面,但客觀的說,這是個人的實現問題,並不是Angular自身問題。
Angular是有它自己體系。Angular的所有操作都必須經過它的digest cycle遍歷監聽器,否則這些元件不能和你的資料模型同步,這也導致了它的相容性問題。如果你還使用任何包含資料變動的第三方Js庫,你需要用Angular的$apply函式包裝它們,否則你就需要把它們轉變成一個服務。這就好比重構每一個JS庫只為它們能夠和Angular相互合作。
依賴注入。JavaScript目前沒有包管理器或者自己的依賴解析器。AMD,UMD和CommonJS已經較好解決了這個缺陷,但是到現在Angular也沒有處理好這些。當然,它引入了依賴注入(DI),儘管如此,但客觀的說,有許多非官方的依賴注入方式使用RequireJS實現。
陡峭的學習曲線。使用Angular需要你學習大量的概念,並不僅僅侷限於以下:
- 模組(modules)
- 控制器(controllers)
- 指令(directives)
- 作用域(scopes)
- 模板(templating)
- 連線函式(link functions)
- 過濾器(filters)
- 依賴注入(dependency injection)
所以初次接觸Angular是非常困難的,它不適合膽小鬼。所有的這些致使我開始轉向React。
React好在哪?
React是最新的開源UI框架,是構建JavaScript應用的新方式,React由Facebook和Instagram領導。
要清楚地是:React並不是像AngularJS那樣的應用開發框架,所以把它們作為同類比較是不公平的。
當React在2013年5月的歐洲JSConf被介紹於眾時,參會者被它的一些概念深深震撼,比如“單方向的資料流”和“虛擬DOM”。
React用於構建UI介面,引用一句來自官方網站的話說,“人們使用React作為MVC中的View”。但是,你可以用它編寫獨立的Web元件,多多少少類似Angular的directives。
React重新思考了我們當今的web發展觀和最佳實踐。比如,它鼓勵單向資料流動,相信元件是被資料驅動的狀態機的哲學。
儘管大多數類似框架喜歡直接操作DOM,React卻討厭DOM並盡力避免開發者與DOM打交道。
React提供了儘可能少的API去實現一個UI元件,既沒有多餘,有沒有不足之處。它遵循了UNIX的哲學:小即是美。做一件事就要做到極致。
這裡有一篇更詳盡的關於Angular和React間的比較的文章,來自於就職Facebook/Instagram的Pete Hunt。
為什麼我轉向了React?
下面列出了React中我喜歡的幾個方面。
React速度很快
跟其他框架相比,React使用不同的方式訪問DOM。它並不讓你直接操作DOM,而是在JavaScript程式碼邏輯和實際DOM間引進了一個叫做“虛擬DOM”的層。
虛擬DOM提高了web效能,對於連續的渲染過程,React在虛擬DOM中得到前後發生的變動(diff),之後只在真實DOM中改變那些需要改變的地方。
很好的瀏覽器相容性
虛擬DOM解決了跨瀏覽器的相容問題,因為它提供了一套支援IE8以上標準的API
模組性
編寫獨立的UI元件讓你的應用模組化,可以讓你把出現的問題限制在有這個問題的模組上。每一個模組都可以被單獨開發、測試,並且能夠呼叫其他元件,這相當於提高了專案的可維護性。
單向資料流更合情合理
Flux是在JavaScript應用中創造單向資料層的系統架構,這個概念和React檢視庫由Facebook一同提出的,Flux的出現讓開發大型應用變得更加簡單。Flux只是一個概念而不是特定工具的實現,它可以成為其他框架的一部分,例如,Alex Rattray有一個不錯的Flux的實現:在React中使用Backbone的集合和模型。
純JavaScript
現在的web app跟傳統的Web相比工作方式已經不同了,比如檢視層通過與使用者的互動改變內容而不是請求伺服器,因此檢視和控制器需要緊密相互依賴。其他一些框架使用Handlebars或Mustache那樣的模組引擎處理檢視層,但是React認為檢視層和控制器相互依賴非常密切以至它們應該共存一處而不是使用第三方模板引擎,當然,最重要的是不要離開JavaScript的作用域。
同構JavaScript
單頁JS Web應用的最大的缺點是在搜尋引擎抓取資料時的限制。React對此有一種解決辦法。
React可以在將資料傳給客戶端前在伺服器上預先渲染應用,這樣可以從伺服器上渲染好的靜態資料還原真實應用的相同狀態。因為搜尋引擎爬蟲抓取資料依靠伺服器的響應而不是JavaScript的執行結果,所有預先渲染可以改善你的SEO
與其他庫相容良好
在構建大型應用的時候,像RequireJS, Browserify和Webpack那樣的載入器和打包工具是十分有用的,它們讓艱難的任務得以完成。不幸的是,目前版本的JavaScript並不提供用於載入和打包的模組(不過有提議在即將到來的ES6版本中加入System.import)
幸運的是,我們擁有像RequireJS和Webpackz這樣簡潔的代替品, React就是用Browserify構建的,如果你想注入影像資源或者編譯Less和CoffeeScript,Webpack或許是一個更好的選擇,更重要的是,你完全可以實現這個選擇。
使用React,我還需要其他開發框架嗎
使用React可以構建使用者介面,但是你仍需要發起AJAX相應,使用資料過濾器或者其他Angular包含的功能。
那麼我們是否需要使用額外的JavaScript開發框架?為什麼我們拋棄Angular?
框架就是一套模組和規則,如果我不需要其中一些模組或者想把一個模組替換成另一個更優秀的模組,我該怎樣做?
其中一種實現模組化和依賴管理的方法就是通過包管理器。但是,我怎麼才能在Angular裡管理包呢?這都取決於你,但是你要知道Angular有它自己的體系,你很可能需要改編第三方包使其適應Angular的體系。換句話說,React就是純淨的JavaScript,任何用JavaScript編寫的第三方包不需要任何包裝就可以使用。
對我來說,使用npm、Bower這樣的包管理器是很好的選擇,我們可以挑選自的己元件和工具集。但需要明確的是:這比使用像Angular這樣的綜合性開發框架更復雜。
這一方面,它的好處是React鼓勵使用npm,這樣就擁有了許多現成的包可以使用,當你開始用React構建app,你可以使用其中一個全棧初學者工具包。
轉換到React並不是輕鬆的
因為Angular是一款app開發框架,它的確帶給我很多好處,但我還是我放棄了一些非常棒的功能,比如將封裝好的AJAX用於$http服務,使用$q作為promise服務,用ng-show,ng-hide,ng-class和ng-if作為模板控制語句——所有這些都令人驚歎。
React並不是一款app開發框架,所以你需要考慮構建應用的其他方面,比如,我正從事一款叫做react-utils的開源專案,以此用來簡化React開發。社群也正在積極地貢獻類似的可重用元件來填補這個空白,React Component就是一個非官方目錄網站,你可以從中尋找這樣的開源元件。
React的哲學並不鼓勵你使用雙向繫結,這會讓你處理表單和可編輯的資料格時帶來了很多困苦。但是,但你開始理解Flux資料流動和儲存的時候,一切都變得清晰簡易。
React是新興的,它的社群需要時間成長,而另一方面Angular已經得到極大流行,有相當多的擴充可以使用(比如AngularUI 和 Restangular)。然而,儘管React的社群剛剛興起,但它成長迅速,像React Bootstrap這樣的擴充可以證明,所以我們擁有更多的元件使用只不過是一個時間問題。
結論
如果你喜歡Angular方式,你可能一開始討厭React,主要是因為React的單向資料流和它缺乏開發應用的特性。但是一旦你開始適應了Flux設計模式和React的哲學,我保證你將會發現它的美麗之處。
Facebook和Instagram都在使用React(因為是它們領導在React)。
GitHub’s新的原始碼編輯器Atom就是用React構建的。
即將到來的新Yahoo!郵箱正在用React構建。
React已經取得大規模的app和大科技公司的關注。