從StackOverflow看Angular 1.x
去年 IE Team 把 issue tracker 放到 StackOverflow 之后,我一度以為 SO 會革了 MSDN Library 和 Forum 的命(也就是讓我丟掉飯碗),就像 GitHub 干掉 Codeplex 和 Google Code 一樣。剛好當時我學習和實踐 AngularJS 有一段時間了,我就想到 SO 上試試身手,看看自己的水平,是否能夠幫助到別人。
于是我每天大概花半個小時不到在 SO 的 Angular JS tag 下面解答問題。玩了半個月左右,拿到一千多分。在 SO 上刷分當然不是目的,但是分數比較好的體現了你回答的問題的準確度和熱門度,所以我比較關注這個指標,但這個過程只能用艱難來形容。之所以稱之為艱難,主要原因有兩個。
- 如果題目比較基礎,解答相對容易。但是你會遇到很多三哥朋友們第一時間沖出來回答。甚至很多時候,你已經做出解答了,他們還源源不斷地 post 和你一模一樣的 answer 。
- 如果題目比較深入,確實沒有三哥和你搶了,但很多時候這也意味著,沒有多少人會關注這個問題,為你的答案點贊。 </ol>
- 在 built-in 的 directive 中,比如<input type="text" name="userName" ng-model="user.name"
- 另一種就是使用 double bracket<p>My first expression: {{ value }}</p>。 </ol>
- ng-disabled
- ng-change
- ng-repeat, ng-repeat-start/ng-repeat-end 。尤其是后者,滿多人上來問,我該怎么用 ng-repeat 實現 xxx 功能,基本都是因為他們不知道 ng-repeat-start/end .
- ng-cloak 玩過 Angular 的同學都知道,如果頁面 loading 比較慢,就會看到頁面上充滿著各種花括號,然后才會變成相應的文字。為了解決這種問題, Angular 給我們提供了 ng-cloak (ng-bind也能實現一樣的效果)。這是我給microsoft.github.io 交的第一個 pr :)
- ng-style/ng-class 在使用 JQuery 的時候,可以直接操作 DOM 來添加樣式,但這并不是 Angular 推薦的方式。很多人意識到了這點,他們只是剛好沒聽說 ngStyle/ngClass 。 </ol>
- Encoding 真的是所有程序員的噩夢。到底是 form 還是 json 還是 byte array ?如何設置 header ?如何配置 callback ?問題 多 多。
- Cache 為了減少 call 后臺的 cost,$http 提供了 cache 的功能。
- Headers 論如何為所有的 $http request 配置 header。
- JSONP
- CORS. Angular 把 rendering engine 搬到了瀏覽器里,我們需要通過 ajax 向 backend server 抓取數據然后在頁面上渲染,這就不可避免的遇到了 cross domain 的各種 failure ,算得上前端屆又一個老 大 難 問題。
- Promise. ASP.NET 有 async/wait,你猜 Angular 里面都 有 啥。
- interceptor. Angular 允許你 customize $http 的 error handling。 </ol>
這兩個現象其實都來源于一個 root cause :基礎的問題,回答起來更容易,花的時間更少,得到的分數更多。而這樣的問題,受到所有人的喜愛。為什么呢?對于搶分狂魔而言,這種題目分數更好得;對于熱心答題不計較分數的好心人而言,回答這種問題,能夠把時間省下來幫助更多的人,何樂而不為?當整個社區都呈現這種狀態是,你就不難得到當年老趙對 SO 的評論:如果你經過深思熟慮也無法解決的問題,丟到 SO 上,也基本上不會得到你想要的答案。這是個悲傷的結論,但 it’s true 。
SO 其實也意識到這個問題了我估計,于是他們搞了個 Golden Badge 叫做Unsung Hero。獲得這個 Badge 的條件是,你超過一半的答案被選為正確答案,但是沒人給你 upvote(也就意味著關注度小)。真的是名副其實,無名英雄。最開始拿到這個 Badge 的時候,我并沒有特別高興。但當我得到上面的結論時,我就釋然了。高興了無聊了工作累了,我就爬上去回答一些我知道的問題。
這幾天突然看到自己又一次上了 AngularJS 這個 Tag 的Last 30 days top answerers,我想,既然在 SO 上最熱門最搶手的問題都是比較基礎的、簡單的,這也間接說明,對于新手而言,這些知識點具備一定學習曲線,并沒有那么容易上手和熟悉。如果把這些知識點和問題做一個整理,這一定是一個不錯的文檔,也能從中看出這個語言或框架在設計方面的不足。于是我從前到后閱讀了一遍我回答過的 Angular 的問題,很快發現不少反復出現或者同類型的提問。
下面讓我們一起,從我的角度,看看大家學習 Angular 1.x 的時候通常會遇到哪些困難。
一:Angular Principles
第一類問題是關于 Angular 的運行原理。像 ASP.NET 這種框架,你大部分時候都不需要理解它的機制,而當你不得不去理解 ASP.NET 是怎么運行,那基本說明你遇到了非常坑爹的問題了。但是 Angular 并不是這樣的,即使你是上手才半個禮拜的新手,當你需要完成一些特定的功能,你就不得不理解 Angular 的 principles,否則你就會掉入坑中爬不出來。這也就是業界對 Angular 最大的批評,學習曲線比較高。
Digest Loop
這是我心目中的 Angular 第一大殺手。很多前端工程師從純 JS 或者別的框架遷移到 Angular 的時候,最經常問的就是,為什么我更新了某某 object 的值,頁面上沒有更新呢? Angular 使用 Digest cycle 來實現 two way binding,而他們的操作并沒有進入到這個 cycle 中,比如 ace update text,show json, image change。 GitHub 上有這樣一群 repo ,他們專門負責把第三方的 library 進行包裝,使得能夠在 Angular 中使用。老實講, Angular 養活了一批人呢。等2.0上市了,大家又要一股腦兒把這些 library 重新包裝,有興趣的同學不妨試試,是個不錯的學習 Angular 和 Contribute to Open Source 的機會。
還有就是在寫 directive 的時候,更新了 model 卻不能刷新 頁面
好不容易 developer 知道可以使用$apply$digest去手動 trigger digest loop,他們也會經常遇到 infinite digest cycle 的問題,簡直要瘋了。
Expressions
Angular 中有你可以這么使用expression
可是奇怪的事情,當你使用ng-src的時候,你需要這樣寫<img ng-src="http://www.gravatar.com/avatar/{{hash}}" alt="Description"/>… 我已經不知道該說什么好了 …你可以再看看這里 1, 2。
$scope
很多人搞不對expression也可能是因為沒有理解 scope 。scope 既是連接 controller 和 view 的膠水,也是 expression 的運行環境。很多朋友在這里栽了,帶來的結果往往是搞不定 data binding 。
Module definition
如果你只是通過官方的demo來學習Angular,你可能會搞不清楚angular.module('app', [])和angular.module('app')的區別,并且由于調用的錯誤,導致 module 不斷地被反復 initialize。
Angular config/run phase
在 module 的 bootstrap 過程中,你可以通過指定自定義的 Configuration blocks 來操作 provider/constants,或者使用 Run blocks 來配置 instances/constants ,千萬不要錯用了。
DI
一般 dependency injection 出現問題,基本都是用戶粗心漏掉了某個 factory ,或者是使用了 minification 。
二:Directive
什么是 directive ,這里我只簡單貼一下官方的說法
At a high level, directives are markers on a DOM element (such as an attribute, element name, comment or CSS class) that tell AngularJS’s HTML compiler ($compile) to attach a specified behavior to that DOM element or even transform the DOM element and its children.
</blockquote>directive 能夠很好滴幫助實現模塊化,在 Angular 在自己的實現過程中,就把不少功能以 directive 的方式提供給開發者。用戶也可以自己書寫 directive 對功能進行抽象。在我看來,directive 往往是初學者比較難以掌握的。
Built-in Directives
首先是 Angular 提供的 directive 。有的時候,即使是認真研習文檔,你也不一定能夠成功理解它們的運行機制,很多朋友在這里就吃了苦頭了。印象里 built-in directive 這個方面我拿分相對容易,因為我比較勤勞,如果文檔不能夠幫助解決問題的話,我會直接跑去看源碼。如果問我泡 StackOverflow 最大的收獲是什么,那一定是讀了不少 Angular 的 source code。
SO 上經常會提及的 built-in directive 有
Write your own directive
除了使用 built-in 的 directive ,Angular 也鼓勵大家來寫自己的 directive。但是這里大家經常會遇到 model binding 或者是如何給 attr 傳值,再或者從 directive 中訪問 controller 的 scope 。
三:$http
$http 只是一個 built-in 的 service ,但我要把它單獨拿出來講一講,一方面是因為這是一個非常基礎的 service (訪問后臺 Rest API ),另一方面是 developer 在和 $http 總會不約而同的想靜靜。
最后,讀者朋友如何跑到我博客首頁看一看,你還能看到去年我對 Angular 的吐槽 Angular 一個值得當心的bug 。是的,我噴的就是 $http ,雖然沒有什么卵用。
四:Best Practice
還有一類問題,來自有理想有追求的朋友。他們想知道如何 think in Angular,如何操作能夠有比較好的 performance等等。
Communication/Data Sharing between Controllers/Factories
當你想在不同的 context 之間共享 data 的時候,全局變量堪稱 fast and dirty 。但不幸的是,從你上大學的第一天開始,就有人不斷告訴你這么做是不負責任滴。于是為了避免被同事 code review 的時候 challenge,不斷有人來問該如何 在 controller/factory/directive/etc 之間 share data 。俗稱,月經帖。
Model binding/Performance Enhancement
其實這個和上文提到的 digest loop 可以放在一起談。Angular 使用了 dirty check 去實現 two-way binding,也就是很傻瓜地反復地遍歷 watch list,看看大家有沒有什么更新。當頁面上的綁定的 element 開始增多(大概2000+),dirty check 就會嚴重拖累整個頁面的 performance。
dirty check 簡直是 Angular 1.x 的阿克琉斯之踵,然后谷歌的大大們在2.0中,把它無情地拋下了。聽聞這個消息,我等屁民“彈冠相慶”,誰讓它老是 折磨 我們 呢。https://rebornix.com/frontend/2015/06/10/NGSummary/
去年四月我第一次接觸 Angular,寫了點自嗨的小玩具,轉眼已經過去十三月了。短短的一年光陰,Angular 1.x 已經確立了不可撼動的一哥地位,而2.0 也已經“洗心革面”馬上要出來重新做人。至于我,在嘗試完各種姿勢之后,也算是找到了一點方向。希望2015年剩下的時間里,做好一個產品,來一點 breaking change。
Breaking Change!! Hell Yeah!!
來自:https://rebornix.com/frontend/2015/06/10/NGSummary/