这两者之间的区别是什么?每种用例有什么用处?
该文档是不完全帮助:
forRoot创建一个包含所有指令,给定路由和路由器服务本身的模块.
forChild创建一个包含所有指令和给定路由的模块,但不包括路由器服务.
我的模糊猜测是,一个用于'main'模块,另一个用于任何导入的模块(因为它们已经可以从主模块获得服务),但我真的不能想到用例.
Max*_*kyi 111
我强烈建议你阅读这篇文章:
导入模块时,通常使用对模块类的引用:
@NgModule({
providers: [AService]
})
export class A {}
-----------------------------------
@NgModule({
imports: [A]
})
export class B
Run Code Online (Sandbox Code Playgroud)
这样,在模块上注册的所有提供程序A都将添加到根注入器,并可用于整个应用程序.
但是还有另一种方法可以向这样的提供者注册模块:
@NgModule({
providers: [AService]
})
class A {}
export const moduleWithProviders = {
ngModule: A,
providers: [AService]
};
----------------------
@NgModule({
imports: [moduleWithProviders]
})
export class B
Run Code Online (Sandbox Code Playgroud)
这与前一个含义相同.
您可能知道延迟加载的模块有自己的注入器.因此,假设您希望注册AService为整个应用程序可用,但有些BService仅适用于延迟加载的模块.您可以像这样重构您的模块:
@NgModule({
providers: [AService]
})
class A {}
export const moduleWithProvidersForRoot = {
ngModule: A,
providers: [AService]
};
export const moduleWithProvidersForChild = {
ngModule: A,
providers: [BService]
};
------------------------------------------
@NgModule({
imports: [moduleWithProvidersForRoot]
})
export class B
// lazy loaded module
@NgModule({
imports: [moduleWithProvidersForChild]
})
export class C
Run Code Online (Sandbox Code Playgroud)
现在BService只适用于延迟加载的子模块,并且AService可用于整个应用程序.
您可以将上面的内容重写为导出的模块,如下所示:
@NgModule({
providers: [AService]
})
class A {
forRoot() {
return {
ngModule: A,
providers: [AService]
}
}
forChild() {
return {
ngModule: A,
providers: [BService]
}
}
}
--------------------------------------
@NgModule({
imports: [A.forRoot()]
})
export class B
// lazy loaded module
@NgModule({
imports: [A.forChild()]
})
export class C
Run Code Online (Sandbox Code Playgroud)
假设它们都使用相同的令牌访问:
export const moduleWithProvidersForRoot = {
ngModule: A,
providers: [{provide: token, useClass: AService}]
};
export const moduleWithProvidersForChild = {
ngModule: A,
providers: [{provide: token, useClass: BService}]
};
Run Code Online (Sandbox Code Playgroud)
当您token从延迟加载的模块请求时,您可以BService按照计划获得单独的配置.
RouterModule使用ROUTES令牌获取特定于模块的所有路由.由于它希望特定于延迟加载模块的路由在此模块中可用(类似于我们的BService),因此它对延迟加载的子模块使用不同的配置:
static forChild(routes: Routes): ModuleWithProviders {
return {
ngModule: RouterModule,
providers: [{provide: ROUTES, multi: true, useValue: routes}]
};
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*cin 25
文档清楚地说明了这种区别的目的是什么:https://angular.io/docs/ts/latest/guide/ngmodule.html# !#core-for-root
仅在根应用程序模块AppModule中调用.在任何其他模块中调用它,特别是在延迟加载的模块中,与意图相反,并且可能产生运行时错误.
记得导入结果; 不要将它添加到任何其他@NgModule列表.
每个应用程序都只有一个起始点(根),其中主要路由服务应该初始化forRoot,而特定"子"功能的路由应该另外注册forChild.它对于子模块和延迟加载的模块非常有用,它们不必在应用程序启动时加载,并且正如@Harry Ninh所说,他们被告知重用RouterService而不是注册新服务,这可能会导致运行时错误.
Roy*_*mir 25
我认为答案是正确的,但我认为缺少了一些东西.
缺少的是"为什么以及它解决了什么?".
好的,让我们开始吧.
首先让我们提一下一些信息:
所有模块都可以访问根服务.
因此,即使是延迟加载的模块也可以使用提供的服务app.module.
如果延迟加载的模块将为自己提供app模块已经提供的服务,会发生什么?将有2个实例.
这不是问题,但有时却是问题.
我们怎么解决呢?只是不要将具有该提供程序的模块导入延迟加载的模块.
故事结局.
这只是为了表明延迟加载的模块有自己的注入点(而不是非延迟加载的模块).
但是当共享(!)模块声明providers 并且该模块是由lazy 和 app.module?导入时会发生什么?再次,就像我们说的那样,两个例子.
那么我们如何在共享模块POV中解决这个问题呢?我们需要一种不使用的方法providers:[]!为什么?因为他们将被自动导入到消费懒惰和app.module,我们不希望这样,因为我们看到每个将有一个不同的实例.
好吧,事实证明我们可以声明一个共享模块,它不会providers:[],但仍然会提供刺激(抱歉:))
怎么样 ?像这样 :
请注意,没有提供者.
但
当app.module将导入带有POV服务的共享模块时会发生什么?没有.
现在,当懒惰模块将导入具有POV服务的共享模块时会发生什么?没有.
通过约定输入手动机制:
你会注意到图片中的提供者有service1和service2
这允许我们导入service2延迟加载的模块和service1非惰性模块.(咳嗽......路由器......咳嗽)
顺便说一下,没有人阻止你forRoot在一个懒惰的模块中打电话.但你将有2个实例,因为app.module也应该这样做 - 所以不要在懒惰的模块中这样做.
此外 - 如果app.module调用forRoot(并且没有人调用forchild) - 那很好,但根注入器只有service1.(适用于所有应用)
那么我们为什么需要呢?我会说 :
它允许共享模块能够分割其不同的提供者,以便与渴望的模块和惰性模块一起使用 - 通过
forRoot和forChild约定.我再说一遍:惯例
而已.
等待!! 关于单身人士没有一句话?那为什么我到处读单身?
嗯 - 它隐藏在^上面的句子中
它允许共享模块能够通过forRoot和forChild 将其不同的提供者分开以与急切模块和惰性模块一起使用.
该公约(!!!)允许它是单-或者更准确地说-如果你不遵循约定-你不是得到一个单例.
所以,如果你只加载forRoot的app.module ,那么你得到的只有一个实例监守你只应调用forRoot它的app.module.
顺便说一句 - 此时你可以忘掉forChild.延迟加载的模块不应该/不会调用forRoot- 所以你在单身的POV中是安全的.
forRoot和forChild不是一个牢不可破的包-它只是没有要求根的点,这显然只会加载app.module 没有给懒惰模块的能力,有自己的服务,而无需创建新的服务-这,应该成为的-singleton.
这个约定为你提供了一个很好的能力forChild- 消耗"仅用于延迟加载的模块的服务".
小智 5
静态forRoot方法:
RouterModule.forRoot(routes)
Run Code Online (Sandbox Code Playgroud)
forRoot 静态方法是为您的应用程序配置根路由模块的方法。当你调用 RouterModule.forRoot(routes) 时,你是在要求 Angular 全局实例化 Router 类的实例。就像 Angular 创建一个新的基础 AppModule 来导入所有功能模块一样,它也提供 AppRoutingModule 来导入所有子路由。
在您通过 Angular CLI 创建的新应用程序中,forRoot 方法实际上已经在 app-routing.module.ts 内部使用。在您的应用程序中,您只想使用 forRoot 方法一次。这是因为此方法告诉 Angular 在底层实例化 Router 类的实例,并且您的应用程序中只能有一个路由器。forRoot 静态方法是确保您使用单例类的模式的一部分。
儿童路线:
RouterModule.forChild(routes)
Run Code Online (Sandbox Code Playgroud)
当您使用 forChild 静态方法时,您基本上是在告诉 Angular,“应用程序中已经有一个可用的 Router 实例,因此请使用该实例注册所有这些路由。” forChild 方法是您将调用以在整个应用程序中注册路由的方法,并且您将在您创建的子路由模块内部使用它。
forChild 静态方法非常有用,因为它通过允许您在应用程序中保持关注点分离来发挥 Angular 模块功能的核心部分。
假设您想在应用程序中为用户设置创建一个新的功能模块,并且该功能将包含一些路由。您可以使用 forChild 方法在应用程序中保持关注点分离,而不是直接将这些路由添加到 AppRoutingModule 中(随着应用程序的增长,这最终会变得站不住脚)。首先,创建一个新的 UserSettingsRoutingModule。
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { UserSettingsComponent } from './user-settings.component';
import { UserProfileComponent } from './user-profile/user-profile.component';
const routes: Routes = [
{
path: 'settings',
component: UserSettingsComponent,
children: [
{
path: 'profile',
component: UserProfileComponent
}
]
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class UserSettingsRoutingModule { }
Run Code Online (Sandbox Code Playgroud)
注意上面 forChild 方法的使用。由于您已经使用了 forRoot 方法,因此您只需将路由注册到已实例化的应用程序路由器即可。
现在您需要像这样创建 UserSettingsModule:
import { NgModule, CommonModule } from '@angular/core';
import { UserSettingsRoutingModule } from './user-settings-routing.module';
@NgModule({
imports: [
CommonModule,
UserSettingsRoutingModule
],
// Configure the rest of your module here
})
export class UserSettingsModule { }
Run Code Online (Sandbox Code Playgroud)
现在你就拥有了!现在您需要做的就是将此 UserSettingsModule 导入到您的根 AppModule 中,并且指向其各自组件的子路由将在您的应用程序中进行配置。
我希望本指南能够帮助您了解 Angular Router 静态方法 forRoot 和 forChild 如何帮助您在应用程序中创建结构良好的路由。有关更多信息,请查看文档
| 归档时间: |
|
| 查看次数: |
68533 次 |
| 最近记录: |