Angular 1.5 Styleguide (ES2015)

使用 ES2015 在 Angular 1.5 中的最佳實踐

說到關于 Angular Styleguide,很多人可能會想到這篇經典的文章。的確,它是一篇非常棒的文章,甚至已經被翻譯成許多種語言(包括中文),在 github 上更是擁有將近 1.9w 個 star。

然而,這次談論的不是它。因為隨著 ES6 的廣泛應用,以及 Angular 1.5 的發布,它有那么一點點不夠時髦(也談不上過時哈~)。

本文的大部分觀點都來自這篇文章(以下簡稱原文),但個人根據工作上積累的一些經驗添并不是完全認同原文的所有想法,并想去除些繁冗的例子,于是就沒有直接翻譯原文。

言歸正傳,下面就來看看使用 ES6 來編寫基于 Angular 1.5 的代碼有哪些最佳實踐。

模塊架構

在 Angular 體系中,所有代碼都是基于模塊的,它來封裝模塊內部的邏輯、模板、路由和子模塊。

模塊劃分

原文將模塊分為 3 大類,分別是:root, component 和 common,并創建相應的文件夾來儲存。

  • root:根模塊組件,用來啟動應用和相應模板
  • component:包含所有可重用的模塊,模塊中可以包含 components, controllers, services, directives, filters and tests
  • common:包含所有業務的模塊(即不可重用,和 component 最大的區別),它可以是頁面布局、導航和頁腳等等。

原文中有詳細的例子,但就如文章開頭所說,在這里就不貼了。

但是,我并不完全認同原文觀點。

因為,common 的翻譯是公共的,在 common 中存放業務代碼也和我們一直以來的做法相悖;其次是,在 Angular 的開發過程中,還是存在一些可以在業務邏輯中公用的代碼,比如 service 和 filter。所以,我更傾向于將它分為 4 部分,分別是 root, app, component 和 common。

  • root:和原文的作法一樣,依舊是用來啟動應用,并包含了應用的模板(并不一定要一個文件夾,可以是根目錄下的一個 app.js 文件)
  • app:類似于之前的 common 模塊,包含所有的業務模塊組件
  • component:同原文的一樣,包含所有可重用的模塊組件
  • common:公用代碼模塊,包含可公用的代碼,如 service 和 filter
附一張項目中的代碼結構圖

模塊導出

使用 ES6 肯定會使用強大的模塊語法,在同 Angular 一同使用時,一定要注意導出的是模塊的名字,而非是 Angular 的模塊對象,這樣才能再另一處被其他模塊注入。

// 精簡了原文的代碼,去除了一些和這節無關的代碼
import angular from 'angular';
import CalendarComponent from './calendar.component';

const calendar = angular
  .module('calendar', [])
  .component('calendar', CalendarComponent)
  .name;

export default calendar;

文件命名

首先,為每個模塊添加 index.js 文件來定義整個模塊,這樣再別的模塊中可以通過文件夾直接引入。

原文使用模塊名.文件內容.文件類型的方式來命名一個文件,如 calendar.controller.js 等。

我完全同意第一個觀點,但第二個中的模塊名就沒有添加的必要,因為文件夾名已經很好的體現了模塊名這個含義。

再附一張項目中的模塊結構圖

組件(Component)

組件是 Angular 1.5 新提出的,是一種特殊的指令,Augular 的源碼中也彰顯了這一點。

它相比指令更多的是數據的單向綁定和生命周期鉤子,盡管我認為所謂的生命周期鉤子只是語法糖,甚至組件它本身就是個語法糖,但這不妨礙它成為 Angular 體系中重要的一部分。因為,它的推出明確的區分了指令和組件,解決了原先指令劃分不清、承擔過多工作的問題。

組件屬性

Property Support
bindings Yes, 只使用 @, <, &,避免使用 =
controller Yes
controllerAs Yes, 默認為 $ctrl
require Yes
template Yes
templateUrl Yes
transclude Yes

控制器(controller)

控制器只應在組件中使用,如果你只想創建一個控制器,那你應創建一個無狀態組件來管理它。

使用 class 關鍵字來創建控制器時要注意以下幾點:

  • 使用 constructor 處理依賴注入
  • 之前提到過,導出模型名,而并不是直接導出模型
  • 使用箭頭函數
  • 使用 $onInit, $onChanges, $postLink$onDestroy 生命周期
    (注意:$onChanges 會在 $onInit之前被調用)
  • 使用默認的控制器 $ctrl,不使用 controllerAs 修改控制器的別名

單向數據流

  • 總是使用 < 單向數據綁定來代替 = 雙向數據綁定
  • 使用 $onChanges 來監聽數據的變化
  • 父組件的方法使用 $event 作為參數傳遞的名字
  • 子組件調用時返回一個包含有 $event 屬性的對象

這是不是看上去很像 Redux?沒錯,原文的作者也是推薦使用 Angular Redux 來管理狀態。

狀態組件(Stateful components)和無狀態組件(Stateless components)

狀態組件和無狀態組件其實分別對應了 Redux 中的容器組件(Smart/Container Components)和展示組件(Dumb/Presentational Components),這部分原作者主要也是表達了在 Angular 中實現單向數據流的理念,但原作者提供的例子并不是完整的 Redux,它沒有單一的 Store 和 Reducer。

指令(Directive)

相信指令大家都很熟悉了,但自從 Angular 1.5 提供了組件,指令的選擇就應當慎重考慮,它應當只在裝飾 DOM 時使用。

  • 不使用 template, templateUrl, scope, bindToControllercontroller 等相關的屬性,如果想用,考慮是不是它可以用 component 來實現
  • 總是使用 restrict: 'A'

指令屬性

Property 是否使用 Why
bindToController No 使用組件替代
compile Yes DOM 操作/事件的預處理
controller No 使用組件替代
controllerAs No 使用組件替代
link functions Yes DOM 操作/事件的處理
multiElement Yes See docs
priority Yes See docs
require No 使用組件替代
restrict Yes 總是使用 restrict: 'A'
scope No 使用組件替代
template No 使用組件替代
templateNamespace Yes (如果必須) See docs
templateUrl No 使用組件替代
transclude No 使用組件替代

服務(Service)

服務主要用于封裝一些不應在組件中處理的業務邏輯和請求。

Angular 提供 2 種創建服務的方式 servicefactory。在 ES6 引入了 class 關鍵字后,它能非常友好地同 service一起工作,所以,無論何時都使用 service 來創建服務。

類 or 方法

原文的標題是常量或類(Constants or Classes),容許我自作主張的修改一下標題,因為我認為原文的實現的區別更主要的在于是使用類或方法去定義一個服務或控制器等。

當然這兩種方法都可以,因為類它本身就是方法的一個語法糖。但是,Angular 2 是重度依賴 class 關鍵字的,所以,我認為還是全部統一使用 class 關鍵字來聲明服務、控制器、過濾器、指令和組件的定義等。

值得注意的是,Angular 組件和指令定義的參數是一個對象,所以在使用 class 定義時,要手動實例化它。

工具

最后,原文作者還推薦了一些工具

  • Babel:編譯工具,這就不多說了,必備神器
  • TypeScript:還是為了 A2
  • Webpack:打包工具,用過都說好
  • ngAnnotate:自動依賴注入,和打包工具一起服用效果更好
  • Angular Redux:狀態管理

以上為個人觀點,歡迎交流。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,698評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,202評論 3 426
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,742評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,580評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,297評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,688評論 1 327
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,693評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,875評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,438評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,183評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,384評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,931評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,612評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,022評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,297評論 1 292
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,093評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,330評論 2 377

推薦閱讀更多精彩內容