1. 程式人生 > >Angular4.0踩坑之路:探索子路由和懶加載

Angular4.0踩坑之路:探索子路由和懶加載

ati clas per 而是 配置 trap child property one

參考文章:

Angular4路由快速入門 http://www.jianshu.com/p/e72c79c6968e

Angular2文檔學習的知識點摘要——Angular模塊(NgModule)http://lib.csdn.net/article/angularjs/59697?knId=641

隨著需求的增加,項目的功能也漸漸復雜起來。這個時候,需要將項目模塊化,將組件、指令和管道打包成內聚的功能塊,正好可以探索一下Angular4中的子路由以及模塊的懶加載。

之前在開發的時候,已經在根模塊實現了簡單的路由功能,可以總結為以下三個步驟:

1、在app.module.ts文件中加載路由庫,[email protected]

/* */,其中appRoutes是路由數組,它定義了具體的路由規則。

import { RouterModule } from @angular/router;

......

@NgModule({
    declarations: [......],
    imports: [
        ......,
        RouterModule.forRoot(appRoutes),
    ],
    providers: [],
    bootstrap: [AppComponent]
})

2、在殼組件中增加導航條,其中routerLink指令指向路由的目標,routerLinkActive為選中的標簽增加css樣式

<a routerLink="/home" routerLinkActive="active"></a>

3、往殼組件的模板中添加一個router-outlet指令,視圖將會被顯示在那裏

<router-outlet></router-outlet>

現在在這個基礎上想要實現子路由以及模塊的懶加載,文章Angular4路由快速入門中講得比較清楚了,這裏記錄一下在開發過程中我所遇到的一些問題以及註意點。

RouterModule.forRoot()RouterModule.forChild()

RouterModule對象為提供了兩個靜態的方法:forRoot()和forChild()來配置路由信息。

RouterModule.forRoot()方法用於在主模塊中定義主要的路由信息,RouterModule.forChild()與 Router.forRoot()方法類似,但它只能應用在特性模塊中。

即根模塊中使用forRoot(),子模塊中使用forChild()。

子路由

假設在我們 /settings 設置頁面下有 /settings/profile/settings/password 兩個頁面,分別表示個人資料頁和修改密碼頁。setting作為一個獨立的功能塊,可以將其封裝成一個特性模塊。它擁有自己獨立的路由,profile和password兩個頁面的路由可以設置成子路由。

import { NgModule } from @angular/core;
import { CommonModule } from [email protected]/common‘;
import { Routes, RouterModule } from @angular/router;

export const ROUTES: Routes = [
  {
    path: ‘‘,
    component: SettingsComponent,
    children: [
      { path: profile, component: ProfileSettingsComponent },
      { path: password, component: PasswordSettingsComponent }
    ]
  }
];

@NgModule({
  imports: [
    CommonModule,//註意這裏引入的CommonModule,它的作用後面會專門講到,這裏不引入的話頁面會報錯
RouterModule.forChild(ROUTES) ], }) export
class SettingsModule {}

在SettingsModule 模塊中我們使用forChild()方法,因為SettingsModule不是我們應用的主模塊。

另一個主要的區別是我們將 SettingsModule 模塊的主路徑設置為空路徑 (‘‘)。因為如果我們路徑設置為 /settings,它將匹配 /settings/settings。通過指定一個空的路徑,它就會匹配 /settings 路徑。

懶加載:loadChildren

在根模塊AppModule中配置setting模塊的路由信息:

export const ROUTES: Routes = [
  {
    path: settings,
    loadChildren: ./settings/settings.module#SettingsModule
  }
];

@NgModule({
  imports: [
    BrowserModule,
    RouterModule.forRoot(ROUTES)
  ],
  // ...
})
export class AppModule {}

這裏使用到了懶加載LoadChildren屬性。這裏沒有將SettingsModule導入到AppModule中,而是通過loadChildren屬性,告訴Angular路由依據loadChildren屬性配置的路徑去加載SettingsModule 模塊。這就是模塊懶加載功能的具體應用,當用戶訪問 /settings/** 路徑的時候,才會加載對應的 SettingsModule 模塊,這減少了應用啟動時加載資源的大小。

loadChildren的屬性值由三部分組成:

需要導入模塊的相對路徑

#分隔符

導出模塊類的名稱

CommonModule模塊

之前說到在特性模塊中要引入CommonModule模塊,我一開始沒有註意到要在特性模塊中引入,結果在路由的時候頁面報錯:

技術分享

技術分享

技術分享

core.es5.js:1020 ERROR Error: Uncaught (in promise): Error: Template parse errors:
Can‘t bind to ‘ngClass‘ since it isn‘t a known property of ‘div‘.

Can‘t bind to ‘ngForOf‘ since it isn‘t a known property of ‘p‘.

Property binding ngForOf not used by any directive on an embedded template. Make sure that the property name is spelled correctly and all directives are listed in the "@NgModule.declarations".

Can‘t bind to ‘ngIf‘ since it isn‘t a known property of ‘div‘.

......

類似這種一大堆錯誤,感覺像是 ‘ngClass‘ ‘ngFor‘ ‘ngIf‘這樣的指令都沒有定義似的。

檢查了好久,發現是因為我在特性模塊中沒有引入CommonModule,引入之後這些錯誤就都消失了。

import { CommonModule } from @angular/common;
@NgModule({
  imports: [
    CommonModule,
    ......
  ],
})

那麽CommonModule模塊具體的作用是什麽呢?看這篇文章

CommonModule提供了很多應用程序中常用的指令,包括NgIf和NgFor等。更準確地說,[email protected]/common的CommonModule中聲明的。

我們在根模塊AppModule中導入了BrowserModule模塊,BrowserModule導入了CommonModule並且重新導出了它。最終的效果是:只要導入BrowserModule就自動獲得了CommonModule中的指令。

導入BrowserModule會讓該模塊公開的所有組件、指令和管道在AppModule下的任何組件模板中直接可用,而不需要額外的繁瑣步驟。但是在其它任何模塊中都不要導入BrowserModule。特性模塊和惰性加載模塊應該改成導入CommonModule。它們不需要重新初始化全應用級的提供商。 如果你在惰性加載模塊中導入BrowserModule,Angular就會拋出一個錯誤

技術分享

以上就是我在這兩天使用Angular子路由和懶加載中遇到的一些問題和總結。

多說一句:辛苦記錄,轉載請註明出處,謝謝~

Angular4.0踩坑之路:探索子路由和懶加載