angular1.x 升級 angular2+ 方案

angular1.x 升級 angular2+ 方案


我給大家提供的是angular1.x和angular5並行,增量式升級方案,這樣大家可以循序漸進升級自己的應用,不想看文字直接demo入手migration-from-angular1.x-to-angular2Plus


 方案1:主體爲angular1.x,逐步將angular1.x當中service、component、filter、controller、route、dependencies升級爲angular5


 方案2: 主體爲angular5,將項目所有js文件先進行一次加工,採用ES6的方式將每個js文件moduleexport出來,再逐步將內容向angular5靠近


我建議選擇方案1增量式升級,通過在同一個應用中一起運行這兩個框架,並且逐個把AngularJS的組件遷移到Angular中。 可以在不必打斷其它業務的前提下,升級應用程序,因爲這項工作可以多人協作完成,在一段時間內逐漸鋪開,下面就方案1展開說明


Hybrid APP主要依賴Angular提供upgrade/static模塊。後面你將隨處可見它的身影。以下手把手教你將angular1.x遷移到angular2+


1、調用 UpgradeModule 來引導 AngularJS


在AngularJS中,我們會把AngularJS的資源添加到angular.module屬性上。 在Angular中,我們會創建一個或多個帶有NgModule裝飾器的類,這些裝飾器用來在元數據中描述Angular資源。在混合式應用中,我們同時運行了兩個版本的Angular。 這意味着我們至少需要AngularJS和Angular各提供一個模塊。要想引導混合式應用,我們在應用中必須同時引導 Angular 和 AngularJS。要先引導 Angular ,然後再調用 UpgradeModule 來引導 AngularJS。


從HTML中移除ng-app和ng-strict-di指令, 創建一個app.module.ts文件,並添加下列NgModule類:

import { UpgradeModule } from '@angular/upgrade/static';
@NgModule({   
  imports: [  
    UpgradeModule
  ]
})
export class AppModule {
  constructor(private upgrade: UpgradeModule) { }    
  ngDoBootstrap() {
    this.upgrade.bootstrap(document.body, ['yourAngularJsAppName'], { strictDi: true });
  }
}

用AppModule.ngDoBootstrap方法中啓動 AngularJS 應用,現在我們就可以使用 platformBrowserDynamic.bootstrapModule 方法來啓動 AppModule 了。

main.ts:

import {AppModule} from './app/app.module';
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";

platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.log(err));

我們就要開始運行AngularJS+5的混合式應用程序了!所有現存的AngularJS代碼會像以前一樣正常工作,但是我們現在也同樣可以運行Angular代碼了


2、將項目中的services逐步升級爲angular5


我們將username-service.js裏面的內容升級爲username-service.ts:

import { Injectable } from '@angular/core';
@Injectable() 
export class UsernameService {
  get() {
    return 'nina'
  }
}
 

要在angular1.x中使用UsernameService,先創建一個downgrade-services.ts文件,這裏將會存放所有angular5服務降級後在angular1.x中使用的服務


downgrade-services.ts:

import * as angular from 'angular';
import { downgradeInjectable } from '@angular/upgrade/static';
import { UsernameService  } from './services/ username-service '; 
angular.module('yourAngularJsAppName')
  .factory('UsernameService', downgradeInjectable(UsernameService));

完成這兩步之後UsernameService就可以在angular1.x controller component service等注入使用了,在angular5中的使用方法這裏就不舉例了,按照angular5的使用方法來就行


3、項目中的filter逐步升級爲angular5的pipe,同時angular1.x的filter依然保留


由於filter的性能問題angular2中已經將filter改爲pipe,angular團隊沒有提供filter升級爲pipe,或者pipe降級爲filter的module,所以angular1.x中使用filter,angular中使用pipe,filter的升級放在component之前,因爲component的template可能會用到


username-pipe.ts:


import { Pipe, PipeTransform } from '@angular/core';
Pipe({
  name: 'username'
})
export class usernamePipe implements PipeTransform { 
  transform(value: string): string {
    return value === 'nina' ? '張三' : value;
  }
}

4、將項目中的component逐步升級爲angular5的component


我們將hero-detail.js裏面的內容升級爲hero-detail.ts:

import { Component, EventEmitter, Input, Output, ViewContainerRef } from '@angular/core';
import { UsernameService } from '../../service/username-service';
@Component({
  selector: 'hero-detail',
  templateUrl: './hero-detail.component.html'
})
export class HeroDetailComponent {
  Public hero: string;
  
  constructor(private usernameService: UsernameService) {
      this.hero = usernameService.get()
  }
}


要在angular1.x中使用hero-detail component,先創建一個downgrade-components.ts文件,這裏將會存放所有angular5組件降級後在angular1.x中使用的組件


downgrade-components.ts:


import * as angular from 'angular';
import { downgradeComponent } from '@angular/upgrade/static';
import { HeroDetailComponent } from './app/components/hero-detail/hero-detail.component';
angular.module('yourAngularJsAppName')
  .directive('heroDetail', downgradeComponent({ component: HeroDetailComponent }) as angular.IDirectiveFactory)

現在你可以在angular1.x中的template中使用hero-detail組件了,組件之間通訊的問題按照angular5的接口寫


5、將angular1.x controller改成angular5 component


現在就剩下controller了,angular2已經取消了controller,controller可以把它當成一個大的component,所以我們按照component的方法重構controller,並且對新的component降級,controller重構之後我們需要修改路由,我們現在使用的還是angular1.x的路由,基本上一個路由對應的是一個controller,這個時候路由可以這樣修改:


假設有個TestContentCtrl,對應的路由是test

.state('test', {
  url: '/test',
  controller: 'TestContentCtrl',
  controllerAs: 'vm',
  templateUrl: './src/controllers/test-content-ctrl.html'
 })

在TestContentCtrl改成test-content component後

.state('test', {
  url: '/test',
  template: '<test-content></test-content>'
 })


6、第三方插件或者庫解決方案


關於項目中引用基於angular1.x的插件或者庫,基本都能找到angular2+的版本,可以將angular2+的版本引入進行降級處理就可以在angular1.x中使用了,但是~~~, angular2+的版本很多API都改了,angular1.x中的對應使用方法可能不存在了,這裏有兩種解決方案


  • 引入angular2+的版本,刪除angular1.x版本,降級後在angular1.x應用中用到該插件的都檢查一次,運用angular2+的版本的API使用該插件

  • 引入angular2+的版本,保留angular1.x版本,angular1.x應用使用angular1.x版本插件,
    angular5應用使用angular2+版本插件,

    方案2增加了項目的體積,相同的插件引用了兩個版本。在不影響首屏加載時間的情況下方案2是不錯的選擇,因爲一次性將所有插件或者庫的API全部過一遍,工作量比較大容易出錯,也不符合我們增量式升級的初衷


現在項目中所有的內容基本都升級爲angular5了,我們可以刪除downgrade-services.ts和downgrade-components.ts這兩個文件了,同時將路由升級爲angular5,刪除angular1.x相關的庫和插件,一個完整的angular5應用就誕生了


如果不是很明白直接看demo:migration-from-angular1.x-to-angular2Plus,喜歡點個贊喲~~~


分享個問題:

如果import angular保錯了,你可以考慮引入@types/angular

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章