轉載自: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
原因:有些文件裏面帶有/// ,若路徑不對文件找不到則無法啓動。
解決辦法:調整文件路徑,或者刪除這些內容。