我目前正在使用Angular 4的异步编译器动态加载外部模块,并使用NgComponentOutlet将其中一个组件添加到DOM中。外部模块在功能上与主应用程序不相交,因此它应该具有其自己的唯一依赖注入器(或者更确切地说,没有访问父模块的提供者的注入器)。但是,如果我使用ReflectiveInjector.resolveAndCreate
创建新的依赖项注入器,则NgComponentOutlet将失败并显示错误No provider for NgModuleRef!
。
在通过NgComponentOutlet进行一些跟踪之后,这似乎是因为NgModuleFactory依赖于渲染器等来创建组件。但是,我一直无法找到一个公开最小依赖注入器的API,类似于提供给根模块的注入器。有没有办法获得这个注入器,或者创建一个仍然包含渲染动态编译组件所需资源的最小依赖注入器?
答案 0 :(得分:1)
无法限制对应用程序注入器的访问,因为它包含应用程序范围的全局提供程序,如ApplicationRef
,ErrorHandler
,rendererFactory
等。此外,只能使用注入器这些提供者因为所有模块提供者都已合并。阅读更多in this answer。
但是,可以限制对父组件定义的提供程序的访问。 Angular为组件使用不同类型的注射器 - 见this answer。为此,您需要将应用程序注入器而不是通过依赖注入器获取的注入器传入模块工厂,并将其传递到组件构造函数中。我现在知道获得此应用程序注入器的唯一方法是这样的:
platform.bootstrapModule(AppModule).then((module) => {
window['rootInjector'] = module.injector;
});
还有平台注入器,您可以轻松获得,但它对我们的目的无用。阅读更多in this answer。因此,假设您已获得应用程序注入器,然后可以将其传递给模块工厂:
System.import('app/b.module').then((module) => {
const appInjector = window['rootInjector'];
const moduleFactory_ = c.compileModuleSync(module.BModule);
const moduleRef = moduleFactory_.create(appInjector);
或者使用ngComponentOutlet
的方式。
另一种可能的方法是获取应用程序范围的依赖关系并将其重新映射到自定义注入器中:
const applicationRef = i.get(ApplicationRef);
const errorHandler = i.get(ErrorHandler);
...
const customInjector = ReflectiveInjector.resolveAndCreate([
{provide: ApplicationRef, useValue: applicationRef},
{provide: ErrorHandler, useValue: errorHandler}
...
]);
但是将来很有可能失败。