民工精髓V:AngularJS在蘇寧云中心的深入實踐
現狀
2013年下半年到2014年,AngularJS作為最熱門的前端MV*框架,吸引了很多眼球,但是到了2014年末,它的光輝逐漸被React所掩蓋,不再像以前那么“火”了。
在各種技術領域人群中,Web前端與客戶端開發者是最時髦的群體。前不久舉行的深JS(JSConf 2015)中,來自臺灣的開發者赫門用一句精辟的戲謔說明了這種狀況:“每18-24個月,前端就會難一倍”。爆炸式的技術增長,層出不窮的新名詞讓人眼花繚亂,作為追隨者,何去何從?
所幸的是,在亂象中,我們仍然可以摸出兩條主線,一條是以AngularJS、Vue.js、avalon為代表的MVVM流,一條是以React 為代表的組件流,這兩者是對前端框架的不同思考方式,各自吸引了很多追隨者。在發展過程中,兩邊的理念也在互相學習,比如Vue.js也逐漸強化組件的概念。
MVVM流的幾個框架中,AngularJS擁有最龐大的周邊,但其實,這些框架的很多第三方組件略加修改之后,都可以很容易互相遷移,除了數據變更監控方式的不同,剩下的都只是模板語法的差異了。
相比其他一些流派,AngularJS的使用群體比較低調一些,因為它的大部分使用者都是管控系統的開發人員,也就是傳統的B/S軟件開發者,有很多之前不是專門做前端開發的,或者是使用類似ExtJS這類框架進行開發的人員。
這兩年,各種社區中可以聽到很多對AngularJS的反對聲音,大部分來自于傳統前端開發人員。
有這么一個有趣的例子,某公司有一些后端開發人員聽說了AngularJS,想要用它開發一個管理后臺,但是害怕自己不能把控,就向前端們提出,希望獲得一些支持,而這家公司的前端們之前也沒有接觸過AngularJS,就同時開始學習。
一周之后,后端們已經順利地用它做了很多功能了,這讓前端們很吃驚,因為他們覺得這個東西很難學。其實,這是由于雙方要補充的技能不同所致,要學會AngularJS,需要這樣的前置技能:
- JavaScript中級水平;
- 具備MV*,分層、注入、模板等知識。 </ul>
- 基于ExtJS這類框架;
- 基于jQuery和相關的插件;
- 基于某一個前端MV*框架。 </ul>
- 路由的管理;
- 代碼的模塊化和動態加載機制;
- 模塊之間數據的共享與通信。 </ul>
- 數據模型是POJO,無需額外封裝;
- 綁定的配置直接寫在HTML里,不必在JS層做判斷、更新;
- ng-click,ng-dblclick等事件作了封裝,“直接”在模板中“調用”控制器上的方法;
- AngularJS自身提供的功能足夠強,$http,$q,jqLite等內置組件使得我們可以基本不引用第三方庫;
- 由于綁定語法的便利性,原先需要“控件”來解決的大部分問題可以輕松解決,也可以少引用很多第三方庫。 </ul>
所以,前端要學的時候,需要補充的是第二項,后端學的時候需要補充第一項。如果具有其他語言的開發經驗,寫出比較規整的JavaScript代碼還是比較容易的,而第二項所列的那些知識,一般的后端開發人員早就在比如SSH這樣的框架組合中習以為常了,所以他們覺得這一切非常自然。
AngularJS可以視為是一種數據優先的框架,在它的三個層面中,數據模型是骨架,視圖模型和業務事件是血肉,視圖模板和指令是皮毛,這三層合在一起,就形成了一個活生生的Web應用。
我們在開發過程中,也應當遵循這樣的實踐,優先從數據模型去考慮問題,然后從展現層去切分模板,最后用視圖模型(控制器)把它們粘合起來。
實踐
從2014年開始,蘇寧的云相關體系逐漸在生產上使用AngularJS,參與人員都不是專職的前端開發人員,比較典型的是蘇寧公有云的控制臺,這是一個典型的管控項目,管理的是IaaS相關的各類資源。
對這么一個產品來說,它的前端部分可以有幾種選擇:
其中,第一種的操作體驗并不很適合在互聯網上使用;第二種對整個團隊前端相關的技能要求較高,也要有一定的代碼組織能力;第三種比較適中,但也需要團隊中有人能熟悉這樣的框架,掌控全局,其他人的技能要求可以比較低,借助Bootstrap之類的樣式庫的響應式特性,還能夠比較容易讓系統在不同設備上可訪問。
目前市面上大多數云控制臺都采用了單頁化的模式,對于這種系統來說,仿客戶端的操作體驗要好很多。這些產品里,使用AngularJS的是主流,也有比如青云這樣的,用的是Backbone。
用單頁模式做控制臺,比較重要的是這么幾點:
在AngularJS體系中,有三個路由庫可以選擇:ngRoute、ui-router和ngNewRoute,在New Route出來之前,大部分人都會選擇ui-router,因為它強大,并且很方便地支持路由的嵌套。
AngularJS本身的模塊機制與主流的AMD、CMD等有一定差距,如果要做動態加載,需要使用一些Hack手段。
很多管控系統并不是一系列很簡單的管理界面的組合,很可能會存在一些聚合與關聯。這時候,就要求我們對數據的共享和通信作一些考慮了。
此外,因為整個系統的單頁化,會存在一些全局性的交互方式。比如說,在某個界面上發起文件上傳之類的長時間操作,在此過程中,如果允許它切換到其它界面繼續操作,上傳過程變成在頁面邊角的一個進度條,然后整個上傳過程一直有動態提示,整個交互體驗就會比較好。這時候,可以考慮在AngularJS中封裝一些service,用于做一些全局統一的交互處理。
使用AngularJS做這類有一定規模的單頁應用,是有很多優勢的。最典型的優勢就是代碼量,實現同樣的功能,AngularJS可以比Backbone之類的少很多代碼量,采用類似架構的Vue.js,avalon也有同等優勢。
代碼主要省在幾個方面:
此外,可以還用一些小技巧讓代碼更精煉。
使用成本
我所見過的幾乎每一篇文章都會說,AngularJS的學習成本高,確實如此,因為要用好它,需要掌握的東西太多了。但是對于一個團隊而言,使用AngularJS的成本并不高,因為團隊是可以有分工,有技能搭配的。
比如,同樣是做一個項目,一個很熟悉AngularJS的人帶著五個只有入門技能的人很順利做出來,因為用AngularJS的話,可以把代碼分得很規整,大部分代碼可以是很簡單的寫法,甚至能夠讓多數參與者在并不了解AngularJS相關機制的情況下把功能中規中矩地實現出來。但是如果用其他一些框架,可能里面至少要有半數人的基礎較好,對個人能力的考驗就相對較高了。
在使用AngularJS的項目中,絕大部分JavaScript代碼都是純邏輯,這部分代碼可以使用ES6這樣很先進的語法編寫,然后通過 Babel轉換成ES5或者ES3代碼執行,熟悉ES6的人會擁有比較高的開發效率。退一步講,如果團隊中存在一些只會使用Java的開發人員,也可以照樣寫出比較規整的邏輯代碼來。
技巧
雖然AngularJS框架本身給我們提供了比較方便的一些功能,也給出了一些Demo,但并不代表我們在實踐過程中就應當這樣去用。針對不同類型的項目,我們需要有針對性地考慮業務代碼的編寫方式,主要包括:
代碼目錄如何劃分?
對于小型項目來說,把代碼按照controller,service之類分層存放比較好一些,但是對于規模較大的項目,這么做其實是不利于代碼管理的。
比較推薦的方式是先按照業務功能做一層目錄劃分,然后在每個業務目錄下再按照分層區分,例如:
…
order
controller
service
template
user
controller
service
template
…
另外有一些全項目通用的東西可以另外建目錄存放,比如對日期時間、貨幣的統一格式化filter等等。
組件與模板
在構建應用的過程中,存在不同的實踐。有人會傾向于大面積的組件化,也就是把業務模塊都封裝成指令(directive,也就是自定義標簽或屬性),然后,整個HTML層會比較清晰。也有人只把“控件”封裝成指令,其他的業務模塊界面只作為模板來處理。
其實兩種都可以用,應當根據團隊人員的技能和項目類型來進行。
對于包含復雜交互效果的界面,進行一定程度的封裝會比較好一些。平常的簡單表單管理之類的,直接用模板比較省事。
如果團隊人員平均技能高,可以試試把更多的東西封裝成指令,如果技能不高的話,使用模板為宜。
業務邏輯放在哪里?
受官方Demo的影響,很多人會忽視service這一層的代碼組織,如果僅僅把這一層當做遠程調用的一種簡單封裝,那是不夠的。
無論使用什么框架,數據層都應當單獨設計。對于單頁應用來說,數據的共享和緩存非常重要,如果不做這個層面的優化,這個應用就還一直停留在初級階段。
在復雜的Web應用中,建議在service層構建數據倉儲,按照業務實體來組織。此外,在復雜的應用中,為實體建立對應的構造函數,也會增強應用的嚴謹性。
自定義事件的使用
在復雜的單頁應用中,模塊間的通信不可避免,自定義事件的廣泛使用可以減少模塊耦合。AngularJS自身的$scope上給我們帶了向上向下兩個方向的事件傳播機制,但在業務代碼層次變深的時候,這種傳遞會變得很啰嗦,所以一般會需要引入全局的事件派發機制,這也就是所謂的 EventEmitter或者EventBus。
我們可以建立一個service專門用于做全局事件的管理,在里面實現一個全局的事件訂閱發布機制,并且在使用的時候用完整業務路徑來命名業務事件。
盡可能重視測試
在使用AngularJS的時候,我們可以遵循最佳實踐,把代碼分層,一層一層逐步構建。這樣,每一層都是非常模塊化的,并且是單向依賴,非常適宜于單元測試。
如果條件具備,可以進一步在這個基礎上做場景測試,甚至做界面發起的自動化測試。測試做到哪一步,用什么方式做,需要視系統與人員的配比狀況而定。在有條件的情況下應當盡可能多做測試,這對系統的穩定性有很大幫助。
未來
2014年末,AngularJS官方披露了2.0版本的一些細節,各種激進和不兼容的變更在整個社區引發了軒然大波。變更的原因無非是迎合標準,并且解決自身的一些歷史問題。
對于開發者來說,將來如何把在用系統遷移到新版本,可能會是一個很重要的考慮點。
應對這個事情,最重要的是保持數據邏輯層面的清晰純凈,盡可能在這一層不依賴于框架的一些特性,然后在遷移的時候,這個部分的改動代價就會很小,大部分的變更都體現在模板層了。
總之,AngularJS框架現在已經進入成熟期,1.4版本大幅優化了性能,也提供了新的路由機制,我們完全可以放心地把它用在以各類管控系統為主的Web應用中,以強大的開發效率去快速推出產品。
作者簡介:
徐飛,網名民工精髓V,目前就職于蘇寧云計算中心,有十年以上大型企業應用前端架構及開發經驗,熟悉AngularJS等框架,對Web組件化有一些思考。博客地址:https://github.com/xufei/blog/issues。
來自:http://www.csdn.net/article/2015-08-24/2825527