NgModule
1,定义
NgModule 是一个带有 @NgModule 装饰器的类,代表一个模块。
2,作用
NgModule把组件、指令和管道打包成内聚的功能块,每个模块聚焦于一个特性区域、业务领域、工作流或通用工具。
3,分类
1)根模块。有且仅有一个,是启动此应用的模块
2)特性模块。特性模块需添加到根模块,通过imports导入根模块或在路由中添加。
特性模块是对代码进行组织的模块,聚焦于特定的一组功能。通过它提供的服务以及共享出的组件、指令和管道来与根模块和其它模块合作。
生成命令为 ng generate module name
特性模块分为5类:
a) 领域特性模块:对某一特定功能的代码进行组织的模块。支持被根模块或其他模块imports后使用。
b) 带路由的特性模块:惰性加载的模块均为带路由的特性模块。模块中有自己的子路由,通过添加到根路由对象中与根模块集成。
c) 路由模块:专注于提供路由配置。
d) 服务特性模块:提供工具服务,如数据访问和消息
e) 可视部件特性模块:如第三方模块和共享NgModule
4,NgModule 元数据属性
1)declarations:声明当前模块所用到的组件、指令和管道,且这些只能属于一个模块
2)providers:声明该模块依赖注入的服务
3)imports:声明需要引入到该模块中的其他模块及其组件、管道、指令
4)exports:声明导出对象供其他模块引用后使用
5)bootstrap:声明应用的根组件,是应用的启动入口
6)entryComponents:声明需动态加载进视图的组件列表
5,入口组件
入口组件属于命令式加载。
包括根组件,路由定义中制定的组件,还包括entryComponents声明的组件。
示例代码:
// 根模块代码示例
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
/* the AppModule class with the @NgModule decorator */
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
6,特性模块具体介绍
-
领域特性模块
包含declarations,罕见providers,导出顶层组件,被特性模块和AppModule导入。
用一个顶层私有组件充当该特性模块的根组件,大部分由declarations组成,只有顶层组件会被导出。只包含少量的服务提供者,服务生命周期与该模块相同。
-
带路由的特性模块
含declarations,罕见providers,无导出,无被导入。
顶层组件作为路由导航的目标组件,所有惰性加载的模块均为路由特性模块。不导出任何文件,不出现在外部组件模块中,不应在AppModule的imports中引用。若被其他模块导入,会变成急性加载,破坏惰性。对比急性加载的模块必须被其他模块imports导入。
路由特性模块很少有服务提供者,其服务须与模块同生命周期。不要在路由特性模块或被路由特性模块导入的模块中提供全应用级的单例服务
| 急性加载 | CLI生成的应用为急性加载,在应用启动时加载。通过依赖注入系统如根注入器让服务在整个应用有效。 |
| 惰性加载 | 需要时被加载,如路由。Angular路由器惰性加载一个模块时,会创建一个新的注入器,作为根注入器的子注入器,路由器把根注入器的所有提供者服务添加到子注入器中,但若服务重复,惰性加载的模块使用提供者创建的服务而不是根注入器的服务,此时服务为局部实例。 |
当应用中包含惰性加载的特性模块,创建应用的命令为:ng new applicationName –routing
创建一个带路由的特性模块(可惰性加载)的命令:ng generate module name--route name --module app.module。该模块不会在根模块app.module.ts中被引用,而是被添加在根路由中的Routes中。支持在根路由中的Routes中添加多个带路由的特性模块。示例代码如下:
// 特性模块的路由文件配置代码
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { CustomersComponent } from './customers.component';
const routes: Routes = [
{
path: '',
component: CustomersComponent
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class CustomersRoutingModule { }
// 在根模块的路由module(app-routing.module.ts )中引入特性模块
const routes: Routes = [
{
path: ‘name’,
loadChildren: () => import('./name/name.module').then(m => m.Name Module)
}
];
-
路由模块
无declarations,有providers(守卫),导出RouterModule,被特性模块导入(供路由使用)。
提供路由配置。命名为:所在模块名+Routing。
根模块使用RouterMdule.forRoot()把把路由添加到import中。其他路由模块为子模块,使用RouterMdule.forChild()。
-
服务模块
无declarations,有providers,无导出,被AppModule导入
服务配置:
1,通常使用 @Injectable({ providedIn: 'root', }) 配置,将服务注入到根注入器中,供整个应用使用,示例代码如下。
2, providedIn也可以赋值为某个模块名,表示服务在配置的模块中可用。
3,或者取消providedIn属性,在所在的模块中providers引用,表示服务在配置的模块中可用,若该模块为根模块则全应用可用。
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class UserService {
}
设置服务为单例模式的方式有:一,@Injectable({ providedIn: 'root', });二,将服务包含在AppModule或被AppModule导入的模块。
出现多个服务实例的情况及解决办法:
1,模块同时定义了providers和declarations,当同时在多个特性模块中加载此模块,这些服务会被注册到多个地方,出现多个实例。
解决:
方法一,服务改为使用providedIn配置,代替在模块中使用providers引入该服务的配置。
方法二,模块分别定义forRoot和forChild方法。把服务提供者从模块中分离,去掉providers的配置。根模块导入时带providers,子模块不带。示例代码如下:
@NgModule({
providers: [ ],
...
})
export class SharedModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: SharedModule,
providers: [
AppUrlService,
AppAuthService,
AppRouteGuard
]
}
}
}
// 使用:在根模块imports中添加 SharedModule.forRoot()
2,每个特性模块须导入RouterModule,但若每个模块都导入RouterModule,则或产生多个实例。,一般根模块导入RouterModule.forRoot,特性模块导入RouterModule.forChild
3,根模块导入一个模块后,若一个惰性模块也导入了它,该应用会为服务生成多个实例。可以通过手动抛异常来检测这个错误行为。示例代码如下
// GreetingModule模块
import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
import { CommonModule } from '@angular/common';
import { GreetingComponent } from './greeting.component';
import { UserServiceConfig } from './user.service';
@NgModule({
imports: [ CommonModule ],
declarations: [ GreetingComponent ],
exports: [ GreetingComponent ]
})
export class GreetingModule {
constructor (@Optional() @SkipSelf() parentModule: GreetingModule) {
if (parentModule) {
throw new Error(
'GreetingModule is already loaded. Import it in the AppModule only');
}
}
}
// 根模块
import { GreetingModule } from './greeting/greeting.module';
@NgModule({
imports: [
GreetingModule,
],
})
-
可视部件特性模块
有declarations,罕见providers,有导出,被特性模块导入。
其中共享NgModule,将常用的指令、管道、组件放入到一个模块中,供其他模块引用。不应该包含providers

1017

被折叠的 条评论
为什么被折叠?



