これら2つの違いは何ですか、またそれぞれの使用例は何ですか?
docs はあまり役に立ちません。
forRootは、すべてのディレクティブ、指定された経路、およびルーターサービス自体を含むモジュールを作成します。
forChildは、すべてのディレクティブと指定された経路を含むモジュールを作成しますが、ルーターサービスは含みません。
私の漠然とした推測は、1つは「メイン」モジュール用で、もう1つはインポートされたモジュール用です(すでにメインモジュールからサービスを利用できるため)、しかし実際にはユースケースを考えることはできません。
この記事を読むことを強くお勧めします。
モジュールをインポートするときは、通常、モジュールクラスへの参照を使用します。
@NgModule({
providers: [AService]
})
export class A {}
-----------------------------------
@NgModule({
imports: [A]
})
export class B
このようにして、モジュールA
に登録されているすべてのプロバイダがルートインジェクタに追加され、アプリケーション全体で利用可能になります。
しかし、このようにプロバイダにモジュールを登録する別の方法があります。
@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
これで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
両方とも同じトークンを使用してアクセスされるとします。
export const moduleWithProvidersForRoot = {
ngModule: A,
providers: [{provide: token, useClass: AService}]
};
export const moduleWithProvidersForChild = {
ngModule: A,
providers: [{provide: token, useClass: BService}]
};
遅延ロードされたモジュールからtoken
を要求したときに別々の設定をすると、BService
が予定通りに得られます。
RouterModuleはROUTES
トークンを使用して、モジュールに固有のすべての経路を取得します。このモジュール内で遅延ロードされたモジュールに固有のルートを利用可能にしたいので(BServiceに似ています)、遅延ロードされた子モジュールに対して異なる設定を使用します。
static forChild(routes: Routes): ModuleWithProviders {
return {
ngModule: RouterModule,
providers: [{provide: ROUTES, multi: true, useValue: routes}]
};
}
ドキュメンテーションには、この区別の目的が何であるかが明確に記載されています。 https://angular.io/docs/ts/latest/guide/ngmodule.html#!#core-for-root
ルートアプリケーションモジュールAppModuleでのみforRootを呼び出します。他のモジュール、特に遅延ロードされたモジュールで呼び出すと、意図に反し、実行時エラーが発生する可能性があります。
結果をインポートすることを忘れないでください。他の@NgModuleリストに追加しないでください。
すべてのアプリケーションには、メインルーティングサービスをforRoot
で初期化する必要がある開始点(ルート)が1つだけあり、特定の「子」機能のルートはforChild
で登録する必要があります。これはアプリケーションの開始時にロードする必要がないサブモジュールや遅延ロードされたモジュールに非常に役立ちます。そして@Harry Ninhが言ったようにそれらは新しいサービスの登録の代わりにRouterServiceを再利用するように言われます。
答えは正しいと思いますが、何かが足りないと思います。
欠けているものは、「なぜ、そしてそれが何を解決するのか」です。
じゃあ始めよう。
まず、情報をいくつか挙げましょう。
すべてのモジュールがルートサービスにアクセスできます。
したがって、遅延ロードされたモジュールでもapp.module
で提供されていたサービスを使うことができます。
遅延ロードされたモジュールが、アプリモジュールが既に提供していたサービスを自分自身に提供するとどうなりますか? 2個のインスタンスがあります。
それは問題ではありませんが、時にはそれはです。
どうすれば解決できますか?単にそのプロバイダのモジュールを遅延ロードされたモジュールにインポートしないでください。
物語の終わり。
これは、遅延ロードされたモジュールが(非遅延ロードされたモジュールとは対照的に)独自のインジェクションポイントを持っていることを示すためだけのものでした。
しかし、shared(!)モジュールがproviders
を宣言し、そのモジュールがlazy とapp.module
によってインポートされるとどうなりますか?繰り返しますが、2つのインスタンスがあります。
それでは、共有モジュールPOVでこれをどのように解決できるでしょうか。 providers:[]
を使うにはnotという方法が必要です。どうして ?それらは、lazyとapp.moduleの両方に自動的にインポートされるため、それぞれが異なるインスタンスを持つことになるので、これは望ましくありません。
providers:[]
を持たない共有モジュールを宣言することはできますが、それでもprodiversを提供することになります(ごめんなさい:))。
どうやって ?このような :
注意、プロバイダはありません。
しかし
app.moduleがPOV of serviceで共有モジュールをインポートするとき、どうなりますか?何もない。
lazyモジュールがPOV of serviceで共有モジュールをインポートするとどうなりますか?何もない。
慣習による手動機構の入力:
あなたは、写真の中のプロバイダーがservice1
とservice2
を持っていることに気付くでしょう
これにより、遅延ロードされたモジュールにはservice2
を、非遅延モジュールにはservice1
をインポートすることができます。 (咳...ルーター....咳)
ところで、だれもあなたがlazyモジュールの中でforRoot
を呼ぶのを止めていません。 app.module
もそうするべきであるので、あなたは2つのインスタンスを持つでしょう - それで怠け者のモジュールでそれをしないでください。
app.module
がforRoot
を呼び出す(そして誰もforchild
を呼び出さない)のであれば - それでも構いませんが、ルートインジェクタはservice1
のみを持ちます。 (すべてのアプリで利用可能)
では、なぜそれが必要なのでしょうか。私は言うでしょう:
forRoot
とforChild
の慣習により、共有モジュールは、その異なるプロバイダを積極的なモジュールや遅延モジュールで使用するためにsplitできるようになります。繰り返します:convention
それでおしまい。
待つ !!シングルトンについての単一の単語ではない?それで、なぜ私はどこでもシングルトンを読みますか?
ええ - それは上の文に隠されています^
共有モジュールは、forRootとforChildを介して、異なるモジュールを積極的なモジュールと遅延モジュールで使用するためにsplitすることができます。
convention(!!!)は、シングルトンになることを可能にします - あるいは、より正確に - あなたが規則に従わない場合 - あなたはNOTシングルトンを取得しないでしょう。app.module
にforRoot
をロードするだけの場合、app.module
にforRoot
を呼び出すだけでよいので、インスタンスは1つしか得られません。
ところで - この時点であなたはforChild
を忘れることができます。遅延ロードされたモジュールはforRoot
を呼び出してはいけません - だからシングルトンのPOVで安全です。
forRootとforChildは壊れないパッケージの1つではありません。遅延モジュールの機能を持たずにapp.module
にのみロードされ、新しいサービスを作成せずに独自のサービスを持つRootを呼び出す意味がないということです。シングルトンになる。
この規約はあなたにforChild
と呼ばれる素晴らしい能力を与えます - 「遅延ロードされたモジュールのためだけのサービス」を消費する。
AppRoutesにサイト内のさまざまな機能(admin crud、user crud、book crud)へのパスが含まれていて、それらを分離したい場合は、単にそれを行うことができます。
imports: [
BrowserModule, HttpModule,
AppRoutingModule,
RouterModule.forRoot(categoriesRoutes),
RouterModule.forRoot(auteursRoutes),
],
ルートの場合:
const auteursRoutes:Routes=[
{path:'auteurs/ajouter',component:CreerAuteurComponent},
]
const categoriesRoutes: Routes = [
{path:'categories/consulter',component:ConsultercategoriesComponent},
{path:'categories/getsouscategoriesbyid/:id',component:GetsouscategoriesbyIDComponent},
{path:'categories/ajout',component:CreerCategorieComponent},
{path:'categories/:id',component:ModifiercategorieComponent},
{path:'souscategories/ajout/:id',component:AjoutersouscategorieComponent},
{path:'souscategories/lecture/:id1',component:SouscategoriesComponent},
{path:'souscategories/modifier/:id1',component:ModifiersupprimersouscategorieComponent},
{path:'uploadfile',component:UploadfileComponent},
{path:'categories',component:ConsultercategoriesComponent},
]