從 Angular 1 升級到 Angular 2 需要準備的步驟

段昕理發表於2016-07-09

我最近在試玩 Angular 2。剛開始感覺很奇怪,和我們鍾愛的第 1 版完全不同。第 1 版是用 ES5 標準的純 javascript 編寫,而第 2 版採用了 typescript 和 es 2015。不過,你已經可以採取一些步驟,讓你的 Angular 1 程式碼(或用 Angular 1 建立的新專案)更加接近 Angular 2。

我為什麼要為 Angular 1 遷移到 Angular 2 做準備

首先,當時機成熟了,你打算用 Angular 2 作為框架時,肯定想讓程式碼遷移更容易些。目前,Angular 小組已經提供了一些遷移策略,你可以混合使用 Angular 1 和 Angular 2 元件,但目標是要將程式碼庫統一,最終只使用一個框架。

其次,在 Angular 2 中更多的是寫純 javascript,然後才是使用專有的框架程式碼。

再次,社群和瀏覽器廠商將逐步擁抱 Ecmascript 的最新標準,所以,堅持使用標準編碼,儘可能讓程式碼庫可複用,而不管選擇的框架是什麼。

遷移到 Angular 2 的步驟

採取這些策略可以讓你的程式碼更加接近 Angular 2,使轉換變得容易。

1. 開始用 Ecmascript 2015

Angular 2 使用 Typescript 編寫,Typescript 是 Ecmascript 2015 的超集,帶有更多的特性。不過,如果你不喜歡 Typescript, 也可以只用 Ecmascript 2015 編寫 angular 2。 目前,程式碼最終都會編譯成 Ecmascript 5。所以實際上你也可以用 Ecmascript 5 來編寫 Angular 2。

但是,在我看來,使用 Ecmascript 2015 的新特性,可以減少程式碼量(有些時候…)、增強程式碼可讀性、用上令人興奮的特性,如解構。

如果想使用 Ecmascript 2015 的特性,你需要一個轉換器來編譯程式碼。目前最流行的轉換器是 babel。babel 在很多流行的構建指令碼中都可以配置,如 gulp、webpack、browserify 及其它。

2. 使用 “angular.service” 替換 “angular.factory”

使用 Ecmascript 2015 意味著我們可以用新的 “class” 關鍵字來建立新物件甚至擴充套件其它物件。我曾經寫過,比起繼承我更熱衷於組合,所以我看不出用 “extend” 實現繼承有什麼用處,不過通過 class 的特性的確可以為建立物件增加好用的語法糖(簡化程式碼)。

在 angular 1 中的 “service” 和 “factory” 的區別是例項化方法:

“service” 使用 “new” 關鍵字呼叫(僅一次)

“factory” 使用普通函式呼叫 — 不需要 “new” 關鍵字。

在 Angular 2 中,Services 使用了 Ecmascript 2015 類編寫。這會導致你需要將 Angular 1 程式碼中的 factories 轉化成 services,並且使用 “class” 替代 function。

例如在我的開源專案-Echoes Player 中,我使用了“class” 和 Angular“service” 編寫 youtube api 服務(我以前用的是 factory):

3. 編寫 Controllers 時使用 “Class” 替換 “function”

這一步和上一步多少有些相似。Angular 1 中的 Controllers 總是不停被重建(或 “新建”)- 因為它們不是單例。

Angular 2 幾乎不用 controllers。

反之,Angular 2 是基於元件的。每個元件都有一個簡單的類(包含少量 es7 註解)來控制。如果你的 Angular 1 程式碼是用 web 元件方式來編寫的,那麼很可能每個指令(directive)都對應一個 controller 函式來控制。

有個很重的點必須意識到 - 指令的概念在 Angular 2 中更加簡單:

  1. 使用了元素選擇器的指令都是元件。
  2. 剩下的都是指令。

Angular 2 仍然會在內部初始化 services 和 controllers,不要自己去初始化,因為那樣會導致程式碼很難測試。不過 Angular 2 還是易於測試並對 TDD (測試驅動開發) 和 BDD(行為驅動開發)友好。我還寫過一篇文章,內容是講為什麼應當封裝 “new” 關鍵字,從而寫出更容易測試的程式碼。

例如把 controller 寫成類,會使程式碼遷移到 angular 2 元件變得非常容易:

4. 使用指令封裝程式碼

在這一步,你需要重新思考程式碼,並且使用更好的架構。從 元件(components)/指令(directives) 的角度開始思考。千萬不要在 index.html 或任何未關聯指令的模板中編寫任何 Angular 程式碼。例如:如果你在一段描述個人資料卡片的程式碼中使用了 ng-repeat, 你可以建立一個指令,“<person-profile-card>” 或者 “<profile-cards>” (作為一個列表)。

在即將推出的 Angular 1.5 版本里,你可以使用 ”angular.component“ 定義來建立元件,使得語法( 出自 todd motto 之手)比指令(directive) 更優美。

記住,元件搭配元件(或指令) 就是 Angular 2 的全部,從這個角度思考,將有助於你更好的重新組織程式碼,也更容易使用 Angular 2。

5. 使用 Angular2to1,ng-upgrade 或其它方法

Angular 2 採用了一個簡單漂亮的語法來定義元件(指令)。為了在 es5 程式碼中體驗 Angular 2 的元件語法,我建立了一個 npm 模組 “angular2to1”。示例,你可以在 Angular 1 應用中使用 Angular 2 的 es5 標準語法來定義一個指令:

這和定義一個 Angular 1 指令等效:

有大量的選項可供使用。

ng-upgraders 是一個程式碼倉庫,包含了 Angular 2 升級策略的資源連結。裡面有一些有趣的專案,有的專案提供了在 Angular 1 中使用 Angular 2 的 typescript 註解及 Ecmascript 2015 的可能性,這樣幾乎可以完全用 Angular 2 的語法來寫 Angular 1 了。

另外,有很多在 Angular 1 中使用 Ecmascript 2015 的解決方案,無論是從軟體架構還是 Angular 推薦架構的角度來看,都堅持了最佳實踐和嚴格準則。

我比較喜歡的一個專案是: NG6-Starter , 專案包含使用 Ecmascrpipt 2015 編寫 Angular 1 應用的骨架程式碼,元件生成器,測試配置和更多內容。

6. (彩蛋)使用模組載入器 system.js、webpack、browserify 或其它工具

所有 Angular 2 例子都依賴於 System.js 庫的元件懶載入機制。System.js 既允許我們使用懶載入,也可以編譯成壓縮好的單一檔案用於生產環境。這樣你就可以在不同的檔案中編寫元件(components)和服務(services),不管構建還是開發,都使用構建指令碼來解決依賴關係。

In addition, if you rather use gulp.js, webpack or browserify – that’s a no brainer and can be easily configured and integrated.

另外,如果你就是喜歡用 gulp.js、webpack 或 browserify - 完全沒理由。沒關係,配置和移植都很簡單。

總結

我傾向於遵守標準。我認為 Ecmascript 2015 最終會成為了 javascript 語言下一代正式標準,所以,有理由去使用它(我之前也寫過)並且擁抱變化。

如果其它的框架、平臺和庫擁抱了 Ecmascript 2015 標準 ,所有人都會受益。大家可以用更靈活的方式編碼,同時在不同的庫和專案中共享程式碼。

相關文章