同 Angular service 的单例特性不同,Angular 组件和指令通常会被多次实例化,比如 HTML markup 中每出现一次 Component 的 selector,就会触发 Component 的一次实例化。
这些 Component 和 Directive 的范围,仅限于导入它们的 NgModule,以防止命名冲突,例如两个组件可能具有相同的选择器。正是由于 Angular 依赖注入 (DI) 行为的这种差异,需要将包含组件和指令的 NgModule 与包含组件、指令和 Providers
的 ModuleWithProviders 区分开来,这就是 forRoot() 方法的用武之地。
然而,依赖注入并不总是这么简单。 有时在引导过程中,所有应用程序的 NgModule 都不可用。延迟加载就是这样一个例子。当在路由期间延迟加载 NgModule 时,在延迟加载的 NgModule 中注册的 providers
,提供程序及其子项在引导过程中不可用,此时 Angular 无法注册它们。 因此,它们仅在加载路由时才作为 providers 添加,而且它们的作用域
是从延迟加载的 NgModule 及其子模块开始注入。
如果有多个延迟加载的 NgModule 尝试注册相同的提供程序,则 NgModule 树的每个节点都会以不同的实例结束。 通过在根目录导入提供程序,它有助于确保所有延迟加载的 NgModule 都获得相同的提供程序实例,这也是为什么 forRoot() 被这样命名的原因。
作为消费者,当应用层序里使用到的某个库依赖项需要一个延迟加载的 NgModule 时,就需要调用其 forRoot 方法。在应用程序的根目录导入模块并使用 forRoot() 方法注册,以全局导入提供程序。在其他 NgModules 中,当需要导入组件和指令时,使用适当的非根形式的导入。
转载请注明:从 Angular Component 和 Directive 的实例化,谈谈 Angular forRoot 方法的命令由来 | 胖虎的工具箱-编程导航