我有以下示例应用程序布局:
app.module
|
|-- dashboard.module (lazy loaded)
|-- dashboard-routing.module (imported by dashboard.module)
|-- dashboard.service (provided by dashboard.module)
|-- dashboard.component (depends on dashboard.service)
|
|-- notifications.module (lazy loaded)
|-- notifications-routing.module (imported by notifications.module)
|-- notifications.service (provided by notifications.module)
|-- notifications.component (depends on notifications.service)
|
|-- my-notifications-dashboard-widget.component <- this should be added
|
|-- ...
每个模块(dashboard
,notifications
,...
)都会延迟加载。
现在我想添加一些MyNotificationsDashboardWidgetComponent
,这取决于notifications.service
。然后,这个小部件应该被注入dashboard.service
。
只要提供的WidgetComponent位于dashboard.module
内,这种方法效果很好。但是如果我把组件放在延迟加载的notifications.module
中,它当然不起作用。
现在我想知道,如何以良好的,面向模块的方式解决这个问题。
我的要求:
应该只有一个 notifications.service
,notifications.component
和my-notifications-dashboard-widget.component
应该使用
大型模块(dashboard
,notifications
)应该是延迟加载的。
dashboard.module
不应该对notifications.module
和/或my-notifications-dashboard-widget.component
了解任何信息。
我想,我需要一些预先加载的模块,其中包含my-notifications-dashboard-widget.component
。因此,在dashboard.module
加载之前, 已知此组件及其提供商。
但是我必须把notifications.service
放在这个模块中,我想?!
dashboard.service:
@Injectable()
export class DashboardService {
constructor(@Inject(DASHBOARD_WIDGET) widgets) {
// inject all provided widgets
widgets.forEach(w => console.log(w.type));
}
}
notifications.module:
@NgModule({
imports: [ NotificationsRoutingModule ],
declarations: [ NotificationsComponent ],
providers: [
NotificationsService,
// this is currently not working, because of lazy loading
{
provide: DASHBOARD_WIDGET,
useValue: {
type: 'my-notifications'
component: MyNotificationsDashboardWidgetComponent
},
multi: true
}
],
entryComponents: [ MyNotificationsDashboardWidgetComponent ]
})
export class NotificationsModule { }
notifications.component:
@Component({ ... })
export class NotificationsComponent {
constructor(service: NotificationsService) { ... }
}
我的通知的仪表板-widget.component:
@Component({ ... })
export class MyNotificationsDashboardWidgetComponent {
constructor(service: NotificationsService) { ... }
}
答案 0 :(得分:3)
请记住,NgModule级别的提供程序始终使用根注入器进行注册。只有一个根注入器,并且使用根注入器注册的任何提供程序都可在应用程序范围内使用。这个规则的例外是延迟加载的模块 - 延迟加载的模块创建自己的范围注入器。换句话说,使用延迟加载的模块注册的任何提供程序都不会向根注入器注册。
为了使用根注入器注册提供者,无论它们是否是延迟加载的,都应遵循forRoot
约定。我们的想法是forRoot
方法返回带有提供程序的模块,以便AppModule可以导入它。
@NgModule({
providers: []
})
export class MyModule {
static forRoot(): ModuleWithProviders {
return {
NgModule: MyModule,
providers: [
MyProvider
]
}
}
}
注意:您还可以使用forChild
方法返回没有提供程序的模块。此方法的目的是使您可以重用模块中的组件(包括延迟加载的模块),而无需实际注册任何提供程序。
答案 1 :(得分:2)
在这种情况下,您只创建一个小部件,将来可能需要添加更多小部件。
解决方案是,创建anohter共享模块并在该模块中创建此类组件。新的共享模块将独立于其他模块及其中的所有组件。
在其他模块中导入共享模块并根据需要使用它。
答案 2 :(得分:-1)
感谢您的灵感。我现在已经创建了一个有效的解决方案它对我来说仍然有点奇怪,有些事情对我来说是一个谜,但至少它是有效的。
如果您可以发表评论并附上一些其他信息,那就太好了
app.module:
@NgModule({
imports: [
AppRoutingModule,
NotificationModule.forRoot()
]
})
export class AppModule { }
APP-routing.module:
@NgModule({
imports: [
RouterModule.forRoot([
{
path: '/dashboard',
loadChildren: 'app/dashboard/dashboard.module#DashboardModule'
},
{
path: '/notifications',
loadChildren: 'app/notification/notification.module#NotificationModule'
}
])
]
})
export class AppRoutingModule { }
dashboard.module:
@NgModule({
providers: [ DashboardService ]
})
export class DashboardModule {
provideWidget(type: string, component: Type<any>) {
return [
{
provide: ANALYZE_FOR_ENTRY_COMPONENTS,
useValue: component,
multi: true
},
{
provide: DASHBOARD_WIDGET,
useValue: {
type: type,
component: component
},
multi: true
}
];
}
}
notification.module:
@NgModule({
imports: [
NotificationRoutingModule
],
declarations: [
NotificationComponent
]
})
export class NotificationModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: NotificationRootModule,
providers: [ ]
}
}
}
通知-root.module:
@NgModule({
declarations: [
TestWidgetComponent
],
providers: [
NotificationService,
DashboardModule.provideWidget('TEST', TestWidgetComponent)
]
})
export class NotificationRootModule { }
我想我完全不理解forRoot
和ModuleWithProviders
。我不明白为什么我必须为此创建一个单独的NotificationRootModule
。
现在TestWidgetComponent
和NotificationService
已编译到app模块中。虽然一切都按预期工作。
但是:如果我在ngModule: NotificationModule
中使用NotificationModule.forRoot()
,那么它会放置整个模块(包括NotificationRoutingModule
和{app}模块中的NotificationComponent
}。 (我可以看到浏览器在打开/notifications
URL时不会延迟加载任何内容。)
现在我不知道providers
属于哪里。我可以将它们放在@NgModule({ providers })
的{{1}}内或NotificationRootModule
内。它似乎没有任何区别。
我希望你能开导我。
谢谢!