AngularJS 為什么成功了?
寫在前面的話 繼上一篇總結之后, 覺得必須補充一下 AngularJS 與 Ionic 的技術性話題 于是, 連夜寫了這第一篇. 講述了 AngularJS 與其他對手之間的優與缺. 我有任何理解錯誤, 請指正.
AngularJS 的成敗
AngularJS 在這兩年時光里, 可謂是異軍突出. 我們來看看 Google 搜索指數:
如果你可以順利KX上網的話, 可以看看這個 指數鏈接
現在, 可以說, AngularJS 在前端領域, 已經占據了主要的地位.
雖然它的誕生, 就像 JavaScript 一樣帶著那樣或這樣的毛病, 但依然大發光彩.
AngularJS 與 JavaScript, 在我看來, 都屬于 2014 年度最佳框架(語言).
我們來詳細談談它的優點與缺點.
全棧 VS 簡單
有人說, AngularJS 太龐大了, 太復雜了, 根本就是發展方向錯誤. 實則不然, 相反, 我的觀點是, 全棧解決方案遠大于簡單的方案.
既然我對 Rails 很熟悉, 我來舉一個 Ruby 界的例子: Rails vs Sinatra. 一個是復雜到 Web 整站解決方案, 既包括了后端, 還包括了前端, 連打包, 壓縮, 布署都幫你做好了. 而另一個則是簡單到極致, 幾行代碼就可以寫一個 Web 服務. 然而, Sinatra 永遠無法打敗 Rails, 只能處于小眾圈子. 因為只要項目一大, 他們就要重新造一遍 Rails 的輪子.
這個時候, 大部分人需要的是全棧解決方案, 不是小而美的東西.
那么, 顯而易見, BackboneJS 與 ReactJS 從這個競爭中出局了.
實際上, AngularJS 像 Rails 一樣, 它內部的輪子是可自由替換的, 事實上, 全棧的背后也是以簡單作為基礎的.
思想的背后
EmberJS 是 AngularJS 強有力的對手, 有很多支持者, EmberJS 的核心實現也是從 Rails 學到了很多東西.
但為什么大家依然選擇了 AngularJS, 我以為真正核心的原因只有一點: 一個框架的哲學思想.
貌似有點深奧, 實際上很簡單: AngularJS 從一誕生, 就認定了一件事: 在 Web 世界里, 聲明式語法要遠遠好于命令式語法. 從這一點, 就引出了 AngularJS 的主要特性:
- 雙向數據綁定
- 永不操作 DOM
而 EmberJS, 一開始就是 Rails 在前端的實現, 當然很多概念不適用, 并且有些特性又不夠, 而現在, 也是補了許多該有的特性, 比如正在開發中的 HTMLBars, View 層無法理解 DOM( HandleBars 只能理解字符串 )是一個硬傷, 這讓 AngularJS 優勢太明顯了: 哲學概念單一, 便于理解. 而 EmberJS, 更像一個后端的思想的框架, 有點水土不服.
或者, 應該換個說法: AngularJS 就像官方想做的那樣, 只是想擴展 HTML 語法, 而不得不造了一些概念. 而 EmberJS 則是為了實現而實現. 如果你深入使用, 自會明白我的意思.
易于上手
AngularJS 真的太容易上手了, 當你做過官網上的 Hello World 例子后, 你就會驚訝: 原來不會 JavaScript 也能寫好 Web2.0.
而 Ember 則一開始就教你理解各種概念, controller, action, template, router. 等一等, 我們需要一步步向上爬.
但是, 沒有銀彈
隨著前端項目的復雜度上升, jQuery 這種命令式語法已經無法管束整個項目的高質量推進. 但 AngularJS 也不是銀彈.
我們俗話有講: 進入一個世界, 往往會放棄另外的世界. 這放與 AngularJS 身上非常合適: 正是 AngularJS 想把它的哲學思想做到極致, 才會帶來諸多新的問題:
- 動態作用域問題
- 依賴注入問題
- digest loop 雙向綁定性能問題
- directives 不必要的復雜度
這幾點, 相信你只要是 AngularJS 深入使用過都會遇到類似問題.
我們看中它的優點, 用它來開發極動感的 AngularJS 前端應用, 也須理解并避開它的缺點.
1. 動態作用域
由于 AngularJS 雙向綁定的需要, 你必須給數據指派一個域( scope ), 就像 JavaScript 中的 function, 會將每個不同的域中的數據隔開開來. 但不同的是, JavaScript 或 Java 等擁有完整語言特性的語言, 它們的 scope 的行為是預定義的, 只有有限的幾種. 而 scope 則不然, 你無法真正理解它, 就無法理解為什么在ng-repeat中修改綁定的值卻對應controller中的值是無效的一樣困惑不解. 但是, 好的是, 當你真正成為程序員時, 你就會豁然開朗.
2. 依賴注入問題
這個問題出現的原因也是由于 AngularJS 的哲學導致: 依賴概念要夠簡單. 開發者想了一個極取巧的方法: 利用參數的名字作為依賴注入的對象. 正是因為 JavaScript 的強大多變, 他們才能做的到. 然而, 新手們總是發現, 坑來了: 為什么壓縮后代碼就不能用了? 高手們說: 我們專門做了個輪子, 避免你打包出錯. 新手們: 好牛X...
3. 雙向綁定的性能問題
雙向綁定的目的是大大提高我們開發者的效率, 卻因為當今瀏覽器引擎的"缺陷"( 無法真正理解事件影響范圍 ), 而只能采用最笨拙的思路:
只要有事件觸發, 就全面執行一次所有的監聽( watcher ), 如果監聽中有新的值出現, 則再次執行所有的監聽, 進行重新計算, 反復最多 10 次.
這里就不解釋原理了. 簡而易見, 這里可能有性能問題.
但經過測試, 只要綁定對象不超過 2000 次, 則每一次 loop 都不會超出 50 ms. 這個時間差對我們人眼是無感知的.
但我認為, 比起這一點潛在的性能問題( 而且是可以輕松調優的, chrome 下有很好用的插件 ), 我們還是值得去學習應用 AngularJS 的.
4. directives 不必要的復雜度
這個問題是唯一一個從設計上欠考慮的模塊了. directives 是一個好東西, 你可以用它來封裝各種 HTML 操作, 然后把它們做成組件. 這個特性太酷了.
本來, 一鼓做氣, 就可以把 ReactJS 比下去, 可是, 由于設計缺失. 我們只能得到一個半成品:
- 語法定義非常蛋疼
- scope 在其中非常繞, 難于理解
- parser, link 等對于普通開發人員暴露的東西太多, 而難于理解. 而問題是, 對于我們普通開發者而言, 這個 directives 特性是我們必修的.
總結
AngularJS 依然擁有不可比擬的優勢, 占據前端開發框架之首也是理所當然. 但 AngularJS 第一代框架確實不夠大氣, 第二代框架又太超前, 我們也不得不像使用 JavaScript 那樣"坑"的語言那樣來使用 AngularJS 了. 因為, 我們確實找不到更滿意的取代品了.
更為可喜的是, AngularJS 的測試框架設計的極為出色, 這也讓它能夠不斷快速迭代, 也讓我們寫的應用更為健壯.
這也是我選擇一個框架的原因之一.
ps: 我是技術達人李亞飛(微信號), 也歡迎關注我的博客:http://yafeilee.me