Angular2文档学习的知识点摘要——Angular模块(NgModule)
目录
前言Angular模块是带有**@NgModule装饰器函数的类。@NgModule接收一个元数据对象,该对象告诉 Angular 如何编译和运行模块代码。 它标记出该模块拥有的组件、指令和管道, 并把它们的一部分公开出去,以便外部组件使用它们。 它可以向应用的依赖注入器中添加服务提供商。参考例子代码:https://angular.cn/docs/ts/latest/guide/ngmodule.html。 Angular模块化 Angular模块把组件、指令和管道打包成内聚的功能块,每个模块聚焦于一个特性区域、业务领域、工作流或通用工具。 AppModule - 应用的根模块 每个Angular应用都有一个根模块类。 在main.ts中引导 在main.ts文件中,我们通过引导AppModule来启动应用。 声明指令和组件服务提供商模块可以往应用的“根依赖入器”中添加提供商,让那些服务在应用中到处可用。 导入支持性模块 Angular能识别NgIf、NgFor等指令的原因,是因为在AppModule中我们导入了BrowserModule模块。 更准确地说, 有些熟悉的Angular指令并不属于CommonModule。例如, 注:永远不要再次声明属于其它模块的类。 解决指令冲突 指令冲突表现在指令同名但功能不同时导入根模块时的情况。即这些指令是不同的,只是恰好指令名称相同而已。 特性模块 特性模块是带有 通过路由器惰性加载模块应用路由app/app-routing.module.ts
COPY CODE
import { NgModule } from '@angular/core';
import { Routes,RouterModule } from '@angular/router';
export const routes: Routes = [
{ path: '',redirectTo: 'contact',pathMatch: 'full'},{ path: 'crisis',loadChildren: 'app/crisis/crisis.module#CrisisModule' },{ path: 'heroes',loadChildren: 'app/hero/hero.module#HeroModule' }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],exports: [RouterModule]
})
export class AppRoutingModule {}
其中,contact路由并不是在这里定义的。对于带有路由组件的特性模块,其标准做法就是让它们定义自己的路由。如,ContactModule特性模块,在其特性区中定义自己的路由文件contact.routing.ts。 { path: 'crisis',loadChildren: 'app/crisis/crisis.module#CrisisModule' },{ path: 'heroes',loadChildren: 'app/hero/hero.module#HeroModule' }
惰性加载模块的位置是字符串而不是类型。在本应用中该字符串同时标记出了模块文件和模块类,两者用 RouterModule.forRoot @NgModule({
imports: [RouterModule.forRoot(routes)],exports: [RouterModule]
})
export class AppRoutingModule {}
该方法返回的AppRoutingModule类是一个路由模块,它同时包含了RouterModule指令和用来生成配置好的Router的依赖注入提供商。 只能在应用的根模块AppModule中调用并导入.forRoot的结果。 在其它模块中导入它,特别是惰性加载模块中,是违反设计目标的并会导致一个运行时错误。 路由到特性模块app/contact目录中也有一个新文件contact-routing.module.ts。 它定义了我们前面提到过的联系人路由,并提供了ContactRoutingModule,就像这样: @NgModule({
imports: [RouterModule.forChild([
{ path: 'contact',component: ContactComponent }
])],exports: [RouterModule]
})
export class ContactRoutingModule {}
这次我们要把路由列表传给RouterModule的forChild方法。 该方法会为特性模块生成另一种对象。 @NgModule({
imports: [ CommonModule,FormsModule,ContactRoutingModule ],declarations: [ ContactComponent,HighlightDirective,AwesomePipe ],providers: [ ContactService ]
})
export class ContactModule { }
现在我们通过路由器导航到ContactComponent,所以也就没有理由公开它了。它也不再需要选择器 (selector)。 也没有模板会再引用ContactComponent。它从 AppComponent 模板中彻底消失了。 路由到惰性加载的模块 惰性加载的HeroModule和CrisisModule与其它特性模块遵循同样的规则。它们和主动加载的ContactModule看上去没有任何区别。 @NgModule({
imports: [ CommonModule,HeroRoutingModule ],declarations: [
HeroComponent,HeroDetailComponent,HeroListComponent,HighlightDirective
]
})
export class HeroModule { }
共享模块 在多个特性模块中,可能存在公共的组件、指令和管道。我们可以添加 import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { AwesomePipe } from './awesome.pipe';
import { HighlightDirective } from './highlight.directive';
@NgModule({
imports: [ CommonModule ],declarations: [ AwesomePipe,HighlightDirective ],exports: [ AwesomePipe,CommonModule,FormsModule ]
})
export class SharedModule { }
值得注意的有: 重新导出其它模块 当回顾应用程序时,我们注意到很多需要SharedModule的组件也同时用到了来自 对于如只在AppComponent中使用一次的组件,我们没必要共享它。如:TitleComponent只被AppComponent用一次,我们就没必要共享它,即不要在SharedModule中导出这样的组件。 核心模块 现在,我们的根目录下只剩下UserService和TitleComponent这两个被根组件AppComponent用到的类没有清理了。 但正如我们已经解释过的,它们无法被包含在SharedModule中。 import {
ModuleWithProviders,NgModule,Optional,SkipSelf } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TitleComponent } from './title.component';
import { UserService } from './user.service';
@NgModule({
imports: [ CommonModule ],declarations: [ TitleComponent ],exports: [ TitleComponent ],providers: [ UserService ]
})
export class CoreModule {
}
因此我们建议把这些一次性的类收集到CoreModule中,并且隐藏它们的实现细节。 简化之后的根模块AppModule导入CoreModule来获取其能力。记住,根模块是整个应用的总指挥,不应该插手过多细节。 用forRoot配置核心服务为应用添加服务提供商的模块也可以同时提供配置那些提供商的功能。 用CoreModule.forRoot配置核心服务 按照约定,模块的静态方法forRoot可以同时提供并配置服务。 它接收一个服务配置对象,并返回一个ModuleWithProviders。 更精确的说法是,Angular 会先累加所有导入的提供商,然后才把它们追加到@NgModule.providers中。 这样可以确保我们显式添加到AppModule中的那些提供商总是优先于从其它模块中导入的提供商。 现在添加CoreModule.forRoot方法,以便配置核心中的UserService。 constructor(@Optional() config: UserServiceConfig) { if (config) { this._userName = config.userName; }
}
这里的CoreModule.forRoot接收UserServiceConfig对象: static forRoot(config: UserServiceConfig): ModuleWithProviders { return { ngModule: CoreModule,providers: [ {provide: UserServiceConfig,useValue: config } ] };
}
最后,我们在AppModule的imports列表中调用它。 imports: [
BrowserModule,ContactModule,CoreModule.forRoot({userName: 'Miss Marple'}),AppRoutingModule
],
注:只在应用的根模块AppModule中调用forRoot。 如果在其它模块(特别是惰性加载模块)中调用它则违反了设计意图,并会导致运行时错误。 禁止重复导入CoreModule 只有根模块AppModule才能导入CoreModule。 如果惰性加载模块导入了它,就会出问题。 constructor (@Optional() @SkipSelf() parentModule: CoreModule) { if (parentModule) { throw new Error( 'CoreModule is already loaded. Import it in the AppModule only'); }
}
参考参考最终版本的全部源码:https://angular.cn/docs/ts/latest/guide/ngmodule.html。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |