Angular RouterModule.forRoot(ROUTES) 和 forChild(ROUTES)的区别

简介: Angular RouterModule.forRoot(ROUTES) 和 forChild(ROUTES)的区别

不少 Angular 初学者在学习 Angular 路由框架时,对 forRootforChild 这两个方法的差异都心生疑惑

Angular 官网对两个方法的解释:


  • orRoot 创建一个包含所有指令、给定路由和路由器服务本身的模块。
  • forChild 创建一个包含所有指令和给定路由的模块,但不包含路由器服务。

但缺乏具体的例子。


Module with providers

当我们导入模块时,通常使用的是对模块类的引用。

例子:

@NgModule({
    providers: [AService]
})
export class A {}
-----------------------------------
@NgModule({
    imports: [A]
})
export class B

通过这种方式,所有在模块 A 上注册的 Service Providers 都将被添加到根注入器中,并可用于整个应用程序。

另一种方式也能工作:

@NgModule({
    providers: [AService]
})
class A {}
export const moduleWithProviders = {
    ngModule: A,
    providers: [AService]
};
----------------------
@NgModule({
    imports: [moduleWithProviders]
})
export class B

我们知道延迟加载模块有自己的注入器。 因此,假设我们要注册 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

这样一来,Service B 将仅对子延迟加载模块可用,而 Service A 将对整个应用程序可用。


上述代码可以进一步重构为:


@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





当我们通过同一个 injection token 获得 Service 的引用实例时,事情就变得更有趣了。


export const moduleWithProvidersForRoot = {
    ngModule: A,
    providers: [{provide: token, useClass: AService}]
};
export const moduleWithProvidersForChild = {
    ngModule: A,
    providers: [{provide: token, useClass: BService}]
};


当从延迟加载的模块使用单独的配置来请求 token 时,我们将获得 Service B 的实例引用。


RouterModule 使用 ROUTES 令牌获取特定于模块的所有路由。 因为它希望特定于延迟加载模块的路由在该模块内可用(类似于我们之前讨论的 Service B),所以它对延迟加载的子模块使用不同的配置:

static forChild(routes: Routes): ModuleWithProviders {
    return {
        ngModule: RouterModule, 
        providers: [{provide: ROUTES, multi: true, useValue: routes}]
    };
}


相关文章
|
12月前
|
测试技术 网络架构 容器
什么是 Angular 的 outlet
什么是 Angular 的 outlet
|
2月前
|
JavaScript 前端开发 测试技术
如何在 Angular 中使用懒加载路由
如何在 Angular 中使用懒加载路由
15 0
|
5月前
|
前端开发
Angular module 的 forRoot 和 forChild 方法
Angular module 的 forRoot 和 forChild 方法
|
11月前
|
前端开发 JavaScript 测试技术
什么是 Angular 的 Custom component
什么是 Angular 的 Custom component
|
12月前
|
设计模式 JavaScript 前端开发
Angular 懒加载模块与 Combined Injector
Angular 懒加载模块与 Combined Injector
|
12月前
|
测试技术 API 开发者
关于 Angular Component ChangeDetectionStrategy.OnPush 策略
关于 Angular Component ChangeDetectionStrategy.OnPush 策略
|
网络架构
Angular RouterModule.forRoot(ROUTES) 和 forChild(ROUTES)的区别
Angular RouterModule.forRoot(ROUTES) 和 forChild(ROUTES)的区别
|
存储 API 网络架构
Angular 14 新的 inject 函数介绍
Angular 14 提供了一些非常有趣的特性:类型化表单(typed forms)、独立组件(standalone components),以及本文将要介绍的内容,即在所谓的构造器阶段(constructor phase) 使用 inject 函数的能力。
关于 Angular 应用 Components 和 Directives 的实例化问题
关于 Angular 应用 Components 和 Directives 的实例化问题
从 Angular Component 和 Directive 的实例化,谈谈 Angular forRoot 方法的命令由来
同 Angular service 的单例特性不同,Angular 组件和指令通常会被多次实例化,比如 HTML markup 中每出现一次 Component 的 selector,就会触发 Component 的一次实例化。