关于 Angular 应用 Components 和 Directives 的实例化问题
同 Angular Module 不同,Angular Components 和 Directives 要实例化多次,每个出现在 HTML template 中的 markup 都会对应一次实例化。
此外,这些项的作用域
也限定在它们被导入的 NgModule中,以防止两个组件使用相同的选择器时发生命名冲突。由于依赖注入(DI)行为的这种差异,需要区分一个包含组件和指令的 NgModule
和一个包含组件、指令和 providers 的 ModuleWithProviders
是很有帮助的,这正是forRoot()方法进行区分的地方。
下面是 SAP Spartacus 关于 forRoot
方法的一个例子:
export class SiteContextModule {
static forRoot(): ModuleWithProviders<SiteContextModule> {
return {
ngModule: SiteContextModule,
providers: [
provideDefaultConfigFactory(defaultSiteContextConfigFactory),
contextServiceMapProvider,
...contextServiceProviders,
...siteContextParamsProviders,
provideConfigValidator(baseSiteConfigValidator),
{
provide: CONFIG_INITIALIZER,
useFactory: initSiteContextConfig,
deps: [SiteContextConfigInitializer, SiteContextConfig],
multi: true,
},
...contextInitializerProviders,
],
};
}
}
然而,依赖注入并不总是这么简单。有些时候,应用程序的所有ngmodule在引导过程中都不可用。延迟加载就是这样一个例子。当在路由过程中惰性加载NgModule时,在惰性加载的NgModule中注册的提供商及其子模块在引导过程中不可用,Angular 那时无法注册它们。因此,它们只有在加载路由时才会被添加为提供商,而且它们的作用域会从惰性加载的NgModule及其子模块开始注入。如果有多个惰性加载 NgModule 试图注册相同的提供商,那么 NgModule 树中的每个节点最终都会拥有不同的实例。通过在根目录下导入提供商,它有助于确保所有惰性加载的 ngmodule 都能获得该提供商的同一个实例,这也是forRoot() 被命名为该实例的原因。
总结
何时使用 Module 的 forRoot 方法?简言之,当一个库的 dependency 需要某个 module 时,就调用该 module 的 forRoot 方法,达到全局(globally
)导入 providers 的目的。
在其他 ngmodule中,必要时使用 import 的非根形式来导入组件和指令。
当一个特性 NgModule 导出的组件和指令需要共享相同的自定义提供商实例时,请考虑用forRoot()方法在根NgModule中注册这些提供商。这有助于确保所有子ngmodule都能访问相同的提供商实例,而不需要使用者显式地处理提供商注册。
相关文章
- 从 Angular Component 和 Directive 的实例化,谈谈 Angular forRoot 方法的命令由来
- node、npm 、package.json、Angular Cli、webpack之间的关系(Windows环境下)
- angular debounce throttle「建议收藏」
- 从 Angular Route 中提前获取数据
- Angular: 最佳实践
- Angular面试题_session面试题
- 关于 Angular 部署以及 index.html 里 base hRef 属性的关联关系
- Angular 应用里 index.html 的作用
- 关于 Angular Universal 应用执行时需要 Browser API 的问题
- 干货 | 一文搞懂在AlmaLinux上安装Angular JavaScript框架
- 【Angular教程】-组件初识|8月更文挑战
- Angular SSR 应用启动时的一些保护措施
- angular.element方法汇总
- Angular用来控制元素的展示与否的原生指令介绍