我对Angular2完全不熟悉,并且很难理解Angular2中@NgModule
导入和导出的情况。
以下面的代码为例:
@NgModule({
imports: [
RouterModule.forChild(heroesRoutes)
],
exports: [
RouterModule
]
})
在导入部分我要导入什么? 路由器模块,或forChild()函数,或函数forChild()返回的模块? 它是哪一个?
当我再次导出RouterModule
时,documentation会说明以下内容:
我们的最后一步是重新导出RouterModule。通过重新出口 RouterModule,我们的功能模块将随路由器提供 使用我们的路由模块时的指令。
这是否意味着无论模块导入上述NgModule,都可以访问RouterModule中的所有代码?
是否有点像我在C中编写包含math.h的自定义头文件,如果我现在使用该头文件,我不再需要在我的程序中单独包含math.h。 我的比喻是否正确?
有人可以在这里解释核心概念,这样每次看到新代码时我都不会感到难过。
答案 0 :(得分:35)
Angular2中的模块与Angular1模块非常相似,Angular1模块基本上是一个包含所有可以一起发货的零碎的包。
例如,如果您有一个LoginComponent,由于某些原因连接到一个服务,即LoginService,它执行一些http请求以获取一些用户信息,您可以创建一个LoginModule,它将LoginComponent和LoginService一起作为LoginModule发送
LoginService也可以使用一些接口,例如UserInterface,再次将其发送到LoginModule是有意义的。
因此,如果我是您的客户并且我将使用您的常规登录功能,那么我将更容易导入您的LoginModule以及我的AppComponent可用的所有好东西!
所以,你的LoginModule类(它只是一个简单的javascript文件和一个函数)应该导出我要使用的LoginModule :)。
LoginModule看起来像这样:
@NgModule({
declaration:[LoginComponent , LogoutComponent],
exports: [
LoginComponent , LogoutComponent
],
providers:[LoginService]
})
export class LoginModule{
}
所以在我的AppModule中,我会导入你的LoginModule。
@NgModule({
imports: [
LoginModule,
RouterModule.forChild(heroesRoutes) // another imported module that I need beside the Login
]
})
但是:
如果我知道你的代码并且我不想要任何额外的函数和组件以及类和东西,我只需要使用你的LoginComponent,我可能更愿意只声明我正在使用LoginComponent而且我不喜欢我想导入你的大量LoginModule!
@NgModule({
declaration:[LoginComponent],
imports: [
RouterModule.forChild(heroesRoutes)
]
})
只有当LoginComponent没有对LoginService有任何直接依赖时,这只会有效,而Angular会抱怨并说:
**No Provider for LoginService**
在这种情况下,如果你是一个坚强的人并且你仍然不相信使用LoginModule,你可以帮助Angular并提供如下的LoginService:
@NgModule({
declaration:[LoginComponent],// declaring it
providers:[LoginService],// providing it
imports: [
RouterModule.forChild(heroesRoutes)
]
});
所以,这可能会继续,您可能会发现导入整个LoginModule更容易,让模块本身完成所有工作。!
这就是LoginModule。
现在,回答有关 forChild 的问题。
LoginModule可能希望在为您提供并不总是需要的类时做一些额外的事情,在这种情况下,您可能已经改进了LoginModule并为其添加了一些糖。
@NgModule({
declaration:[LoginComponent , LogoutComponent],
exports: [LoginComponent , LogoutComponent],
providers:[LoginService]
})
export class LoginModule{
public static logAndLoadModule(message){
console.log('I first log and then give you my module');
return {
ngModule: LoginModule
}
}
public static alertAndLoadModule(message){
alert('I first alert and then give you my module');
return {
ngModule: LoginModule
}
}
}
在这种情况下,看起来模块可以在开始给我它的包时记录一些东西。所以我可能会这样使用它:
@NgModule({
imports: [
LoginModule.logAndLoadModule(),
RouterModule.forChild(heroesRoutes)
]
})
logAndLoadModule 这与RouterModule的 forChild 功能类似吗?
是的,它仍然给你LoginModule,但它也做了一些额外的事情。
因此您仍然可以导入LoginModule,但您也可以使用它的警报和日志。
更新:
导出类LoginModule ,意思是,当前文件(可能是login.module.ts或其他)正在导出一个名为LoginModule的类,它可以从其他文件导入,它与Angular无关,这只是将编译为javascript的打字稿。
在哪里
@NgModule({
exports: [
LoginModulesBrother
]
})
export class LoginModule{
}
上面是Angular2特定的语言,意味着LoginModule也是导出LoginModulesBrother,所以谁曾经导入LoginModule,也可以访问LoginModulesBrother。
因此,LoginModulesBrother是另一个可能在其他地方定义的模块,如:
@NgModule({
// some other magic here
})
export class LoginModulesBrother{
}
所以一般来说,导入和导出类,这可能是什么(模块组件管道是一个简单的函数或任何东西)只是打字稿,但导出数组和导入数组只是角度特定语言对打字稿没有任何意义。
答案 1 :(得分:3)
如果您使用<router-outlet>
组件或routerLink
或routerLinkActive
指令,则需要将RouterModule
添加到您想要的每个模块的imports: []
使用其中任何一种。
对于任何指令,组件或管道,这都是相同的。 Angular仅在模块中实例化它们,如果它们被导入所知。
如果将模块添加到imports: []
所有指令,导出模块中可以使用导出中列出的组件和管道。
模块还可以重新导出其他模块,这使得导入模块可以使用这些模块的所有导出指令,组件和管道。
另见
答案 2 :(得分:0)
来自RouterModule文档:
forRoot
创建一个包含所有指令,给定路由和路由器服务本身的模块。forChild
创建一个包含所有指令和给定路由的模块,但不包含路由器服务。您使用forRoot
为您的根模块配置路由,并为您的功能模块配置forChild
。
您在功能模块中不需要router service
,因为您只需要一个适用于您的应用程序的应用程序,您应按惯例在AppRoutingModule
中配置(假设您的根模块名为AppModule
)
以您的代码段为例:
@NgModule({
imports: [
RouterModule.forChild(heroesRoutes)
],
exports: [
RouterModule
]
})
export class AppRoutingModule {}
RouterModule
有一些声明,例如routerLink
或routerLinkActive
,AppModule
中的组件可能会使用这些声明。
要在AppModule
中提供这些声明,您可以将RouterModule
直接导入AppModule
,也可以通过导出AppRoutingModule
使其可用。