我正在使用Angular 6+为我们的项目构建一个内部库。
我正在使用.forRoot()
方法来注册已记录的全局服务。
我的图书馆将使用ngx-toastr
来提供通知。因为我不希望每个项目都直接处理ngx-toastr
的所有选项,所以我将其中的大部分抽象到了notifications
服务的后面。
ngx-toastr
的工作方式,您可以通过将全局选项传递给ToastrModule.forRoot()
来设置全局选项。
如何将ToastrModule
配置为自己的forRoot()
的一部分?
在.forRoot()
内添加任何代码显然不是一个好主意,但是直接在我的@NgModule()
中对其进行初始化的正确方法是正确的方法吗?像这样:
@NgModule({
imports: [ToastrModule.forRoot(/* options go here? */)],
declarations: [],
exports: []
})
export class ToolsCoreModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: ToolsCoreModule,
providers: [],
};
}
}
如果团队中的某人决定在自己的模块初始化中也调用ToastrModule.forRoot()
,这将如何交互?
答案 0 :(得分:1)
通过providers
导出通知服务的根模块应该是在ToastrModule.forRoot()
声明中使用imports
的唯一模块。
forRoot()
调用是一个约定,不是框架强制执行的约定。其他人在定义他们的NgModules时不应该调用它,如果已经被更高版本调用了。
As mentioned in the Angular documentation:
仅在根应用程序模块
.forRoot()
中调用并导入AppModule
结果。将其导入任何其他模块(尤其是在延迟加载的模块中)与意图相反,并且可能会产生运行时错误。...
forRoot()
和forChild()
是分别在根模块和功能模块中配置服务的方法的常规名称。
如果您对ToastrModule
的全局配置从未改变,那么按照您在代码段中所质疑的方式进行操作,我认为这没有错。
但是,如果配置可能因ToolsCoreModule
的使用者而异,则不应为每个不同的配置调用forRoot()
,因为按照惯例这是错误的。在这种情况下,您可以考虑围绕toast调用的第三个参数创建包装程序,以传递通用配置(例如this.toastrService.error(msg, title, config)
)。
答案 1 :(得分:0)
正如@migh 提到的,forRoot()
应该只由 AppModule
调用,但是 forRoot()
提供程序中的嵌套 forRoot()
仍然由 AppModule
调用,不是吗?
所以您可以执行以下操作
@NgModule({
imports: [],
declarations: [],
exports: [ToastrModule]
})
export class ToolsCoreModule {
static forRoot(/* your options */): ModuleWithProviders {
return {
ngModule: ToolsCoreModule,
providers: [...ToastrModule.forRoot(/* toastr options */).providers],
};
}
}
<块引用>
如果团队中的某个人决定在他们自己的模块初始化中也调用 ToastrModule.forRoot()
,这将如何交互?
您可能会收到运行时错误或奇怪的行为。
为了避免“奇怪的行为”,您还应该将此模式添加到防止双重注册的模块中:
constructor(@Optional() @SkipSelf() parentModule?: ToolsCoreModule)
{
if (parentModule)
{
throw new Error(
"ToolsCoreModule is already loaded. Import it in the AppModule only!");
}
}
该模式来自官方文档: https://angular.io/guide/singleton-services#prevent-reimport-of-the-greetingmodule