【個人筆記重點,不作爲參考】主題:Angular2- 從 beta 到 release4.0 版本升級總結

轉載自:https://www.qcloud.com/community/article/832946?fromSource=gwzcw.149714.149714.149714

一、版本說明

原始版本: 2.0.0-beta.6

目標版本: 4.1.1

新增腳手架: Angular-cli

腳手架版本: 1.0.0-rc.1

升級後主要依賴版本如下:


"dependencies": {
    "@angular/common": "^4.0.0",
    "@angular/compiler": "^4.0.0",
    "@angular/compiler-cli": "^4.0.0",
    "@angular/core": "^4.0.0",
    "@angular/forms": "^4.0.0",
    "@angular/http": "^4.0.0",
    "@angular/platform-browser": "^4.0.0",
    "@angular/platform-browser-dynamic": "^4.0.0",
    "@angular/router": "^4.0.0",
    "core-js": "^2.4.1",
    "rxjs": "^5.1.0",
    "zone.js": "^0.8.4"
},
"devDependencies": {
    "@angular/cli": "1.0.0-rc.1",
    "ts-node": "~2.0.0",
    "tslint": "~4.5.0",
    "typescript": "~2.1.0"
}

二、依賴更改

依賴導入更改:

'angular2/core' => '@angular/core'

'angular2/http' => '@angular/http'

'angular2/router' => '@angular/router'

// 表單相關的

'angular2/commom' => '@angular/forms'

三、新增NgModule

官方說明

Angular 模塊能幫你把應用組織成多個內聚的功能塊。

Angular 模塊是帶有 @NgModule 裝飾器函數的類。 @NgModule 接收一個元數據對象,該對象告訴 Angular 如何編譯和運行模塊代碼。 它標記出該模塊擁有的組件、指令和管道, 並把它們的一部分公開出去,以便外部組件使用它們。 它可以嚮應用的依賴注入器中添加服務提供商。

具體請參考官方文檔

管理公用組件

  • 創建SharedModule管理所有公用組件
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {FormsModule} from '@angular/forms';
// 引入公用組件
import {SomeService} from './service/some.service';
import {SomeComponent} from './component/some.component';
import {SomePipe} from './pipe/some.pipe';
import {SomeDirective} from './directive/ng-file-select.directive';

@NgModule({
  imports: [CommonModule, FormsModule],
  declarations: [SomeComponent, SomePipe, SomeDirective],
  exports: [CommonModule, FormsModule, SomeComponent, SomePipe],
  providers: [SomeService]
})
export class SharedModule {}
  • 其他模塊只需要引入SharedModule
import {NgModule} from '@angular/core';
// 引入SharedModule
import {SharedModule} from 'shared/shared.module';
// 該模塊路由
import {SomeRoutingModule} from './main-routing.module';
// 該模塊相關Component
import {SomeComponent} from './main.component';

@NgModule({
  imports: [SharedModule, SomeRoutingModule],
  declarations: [SomeComponent],
  exports: [SomeComponent]
})
export class SomeModule {
}

四、路由相關

變更

拆分和新增了路由模塊

  • ActivatedRoute:獲取路由信息

  • 路由事件實例,如NavigationEnd表示導航事件變更完畢,等

  • 反正改了挺多的,請自行查詢官方API文檔…[捂臉]

新增路由模塊

路由使用NgModule創建,示例如下:

import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';

import {SomeComponent} from './main.component';
import {ListComponent} from './list.component';
import {DetailComponent} from './detail.component';

const routes: Routes = [ 
  // 這裏displayName主要供麪包屑使用
  {path: '', component: SomeComponent, data: {displayName: '某個模塊'},
  children: [
    {path: 'list', component: ListComponent, data: {displayName: '列表'}},
    {path: 'list', component: DetailComponent, data: {displayName: '詳情'}},
    {path: '**', redirectTo: 'list'}
  ]},
];
@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],
  providers: []
})
export class SomeRoutingModule {}

路由相關常用

// 監聽導航事件變更
// router: Router
router.events.filter(event => event instanceof NavigationEnd).subscribe(event => {});
// 獲取路由信息
// activatedRoute: ActivatedRoute
const rootRoute: ActivatedRoute = activatedRoute.root // 獲取根路由
const children: ActivatedRoute[] = rootRoute.children; // 獲取子路由
// 遍歷子路由,獲取其params/data/url等
for (const child of children) {
     console.log(child.snapshot.data); // 獲取data
     console.log(child.snapshot.params); // 獲取params
     console.log(child.snapshot.url, child.snapshot.url[0].path); // 獲取url或path信息
}

若要寫麪包屑功能,可參考該文章Angular2 Breadcrumb using Router

五、表單相關

依賴API更改


// 依賴中某些API更改
// ControlGroup => FormGroup
import {ControlGroup} from 'angular2/commom';
=> import {FormGroup} from '@angular/forms';
// Control => FormControl
import {Control} from 'angular2/commom';
=> import {FormControl} from '@angular/forms';

原使用[ngFormModel]屬性

  • 更改表單屬性 [ngFormModel] 爲 [formGroup]
<form [ngFormModel]="myform" /> => <form [formGroup]="myform" />
  • 同時在module文件需引入FormsModule和ReactiveFormsModule
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
  • 更改表單內input屬性[ngFormControl]爲formControlName
<input [ngFormControl]="url" /> => <input formControlName="url" />
  • 若要在[ngFormModel]屬性的<form>內使用ngModel,需添加
[ngModelOptions]="{standalone: true}"屬性
<input name="url" [(ngModel)]="url" [ngModelOptions]="{standalone: true}" />
若要在[ngFormModel]屬性的<form>內使用#url="ngForm"來進行驗證,需更改驗證url.valad爲mgform.controls.url.valid
原使用ngForm

更改表單內input屬性ngControl="url"爲#url="ngModel"
同時需要在該input標籤添加name屬性
<input ngControl="url" /> => <input #url="ngModel" name="url" />
若不需要表單驗證,則不需添加name屬性,而添加[ngModelOptions]="{standalone: true}"
<input #url="ngModel" /> => <input #url="ngModel" [ngModelOptions]="{standalone: true}" />
組件封裝使用[(ngModel)]

使用時需加上name以及ngDefaultControl兩個屬性
<date-time-picker [(ngModel)]="start_time" /> 
=> <date-time-picker name="start_time" [(ngModel)]="start_time" ngDefaultControl />

六、其他問題

1. http請求內容帶url時後臺解析錯誤

原因:angular(v4.0.0)中封裝的http服務對參數standardEncoding編碼方法,見node_modules/@angular/http/@angular/http.js文件,導致後臺獲取圖片地址失敗。
解決辦法:使用encodeURIComponent覆蓋standardEncoding編碼

/**
 * 覆蓋原有的standardEncoding方法,見http.js文件
 */
class MyQueryEncoder extends QueryEncoder {
  encodeKey(k: string): string {
    return encodeURIComponent(k);
  }
  encodeValue(v: string): string {
    return encodeURIComponent(v);
  }
}

2. 組件遷移後,無法正確訂閱事件

原因:angular(v4.0.0)中依賴注入,若在不同地方聲明provider,則會創建不同的實例。

解決辦法:在app根組件聲明provider注入ResultHandler服務,則整個app使用同一個實例。

3. 升級angular-cli版本失敗

原因:angular-cli版本升級後,對應webpack版本修改了默認的disableHostCheck屬性,導致ng serve --port會出現Invalid Host header。
解決辦法:回退版本,或者手動更改node_modules裏webpack相關配置(可查看nvalid Host header after updating to 1.0.1 #6070)

4. 運行npm run build --prod命令失敗

原因:basically the problem is in AOT and Angular analyzer. It analyzes code in all cases whether you wanted to have aot or not.
解決辦法:1) -prod => --prod --aot=false 2) -prod => --env=prod(可查看ng build -prod Module not found: Error: Can’t resolve ‘./$$_gendir/app/app.module.ngfactory’ #4551)

PS:運行代碼可通過:即時JIT編譯器動態引導、使用預編譯器( AoT - Ahead-Of-Time )兩種方式。進行靜態引導.靜態方案可以生成更小,啓動更快的應用,默認優先使用。但此處因爲有些動態計算環境的代碼,故編譯失敗,此處手動關閉。

5. 升級angular(v2.4.0)到(v4.1.1)版本後,左側導航的狀態定位失效

原因:升級後,router和component的hook順序調整(僅根據個人觀察,未經驗證),導致組件狀態未能在路由事件結束(NavigationEnd)時完成更新。
解決辦法:目前在路由事件結束(NavigationEnd)時,手動更新組件狀態。

的內嵌樣式失效。" class="reference-link" >6. html模版裏,在style裏使用style="color: {{someValidation ? 'red' : ''}}"的內嵌樣式失效。

原因:angular(v4.1.1)中,需使用[ngStyle]屬性方式對樣式進行設置。
解決辦法:1) 更改爲[ngStyle]="{'color': someValidation ? 'red' : ''}" 2) 更改爲[style.color]="someValidation ? 'red' : ''"

7. 在webstorm裏,更改文件不能在瀏覽器中更新輸出。

原因:webstorm裏面默認啓用”safe write”,將保存先存到臨時文件。
解決辦法:關閉File > Settings... > System Settings > Use "safe write",參見angular-cli issue#5507 。

8. 無法從router裏獲取RouteParams的API。

原因:angular(v4.1.1)中,使用ActivatedRoute的API獲取路由信息。

原代碼:


import { RouteParams } from 'angular2/router';
... // 其餘代碼
    ngOnInit() {
        this.id = parseInt(this._routeParams.get('id'));
        this.needSaveBtn = (this._routeParams.get('action') || '') != 'detail';//查看、編輯、添加
        ... // 其餘代碼
    }
... // 其餘代碼

新代碼:

import { ActivatedRoute } from '@angular/router';
... // 其餘代碼
    ngOnInit() {
      this._route.params
        .subscribe((params) => {
          this.id = parseInt(params['id']);
          this.needSaveBtn = (params['action'] || '') != 'detail';//查看、編輯、添加
         ... // 其餘代碼
        });
    }
... // 其餘代碼

9. 使用angular-cli後無法自定義webpack的alias, 導致文件引入路徑很長,如../../../shared/。

原因:angular-cli內部封裝了webpack配置,若手動改動node_modules不方便。
解決辦法:查看fix(build): use baseUrl and paths from tsconfig #2470,該issue只針對性調整shared目錄,具體可查看相關Commit信息

使用方式:

// 在src/目錄下修改tsconfig.app.json
{
  "compilerOptions": {
    ...
    // 添加路徑相關
    "baseUrl": ".",
    "paths": {
      "@shared/*": ["app/shared/*"]
    }
    ...
  },
  ...
}

// 在根目錄下修改tsconfig.json
// 主要用於編譯器IDE檢測使用
{
  "compilerOptions": {
    ...
    // 添加路徑相關
    "baseUrl": ".",
    "paths": {
      "@shared/*": ["src/app/shared/*"]
    }
    ...
  },
  ...
}

10.升級angular(v4.1.1)版本後,組件遷移狀態更新失效

原因:升級後,component的hook順序調整,導致組件狀態未能在component狀態更新後完成更新。

解決辦法:檢測狀態變更時,需手動再添加狀態更新。

11.升級angular到(v4.1.1)版本後,<iframe>等帶動態src等屬性觸發error

原因:angular2啓用安全無害化處理,爲防止XSS等攻擊,具體可參考官方文檔安全。

解決辦法:注入DomSanitizer服務可以把一個值標記爲可信任的,這裏添加了一個叫safeUrl的pipe組件,位於app/shared/pipe/safe-url.main.pipe.ts。
使用方式:<iframe [src]="url | safeUrl">

12.遷移一些文件後,啓動app失敗,出現Cannot read property 'length' of undefined

原因:有些文件裏面帶有/// ,若路徑不對文件找不到則無法啓動。

解決辦法:調整文件路徑,或者刪除這些內容。

發佈了34 篇原創文章 · 獲贊 6 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章