繁体   English   中英

@NgModule static forRoot 实现动态模块时

[英]@NgModule static forRoot when implementing dynamic modules

我在@NgModule 中有这段代码:

@NgModule({
 declarations: [
   AppComponent,
   DashboardComponent
 ],
 imports: [
   BrowserModule,
   BrowserAnimationsModule,
   ClarityModule,
   RouterModule.forRoot([
     {
       path: '', redirectTo: 'dashboard', pathMatch: 'full'
     },
     {
       path: 'dashboard', component: DashboardComponent
     },
   ], {useHash: true}),
   LibraryTestModule.forRoot(ServicetestService),
   HttpModule
 ],

如果您可以看到我正在将 ServicetestService 注入 LibraryTestModule。

但在我的情况下,我使用下面的代码使用 system.js 动态加载这个模块:

// now, import the new module
    return SystemJS.import(`${url}`).then((module) => {
        console.log(module);

        return SystemJS.import(`${url}`).then((module) => {
            console.log(module);
            return this.compiler.compileModuleAndAllComponentsAsync(module[`${moduleInfo.moduleName}`]).then(compiled => {
                console.log(compiled);
                return module;
            });
        });
    });

现在有什么方法可以在动态加载模块时将 ServiceTestService 注入到compileModuleAndAllComponentsAsync方法中?

经过一段时间的探索,我想我已经找到了解决方案。

小部件.module.ts

export const DYNAMIC_CONFIG = new InjectionToken('DYNAMIC_CONFIG');

@NgModule({
  imports: [
    CommonModule,
  ],
  declarations: [WidgetComponent],
  entryComponents: [WidgetComponent]

  providers: [
  ]
})
export class WidgetModule { }

现在让我们假设您正在将此模块动态加载到 shell 组件中:

shell.component.ts

ngOnInit () {
    const parentInjector = Injector.create({
        providers: [
            { provide: DYNAMIC_CONFIG, useValue: { message: 'CUSTOM VALUE PROVIDED BY THE CONSUME!' } }
        ],
        parent: this.inj
    });

    import('./widget/widget.module.ts')
        .then(m => {
            this.compiler.compileModuleAndAllComponentsAsync(m.WidgetModule)
                .then(moduleWithCompFactories => {
                    const module = moduleWithCompFactories.ngModuleFactory.create(parentInjector);

                    /**
                     * Adding the components from the lazy-loaded module
                     * into the current view
                     */
                    this.vc.createComponent(moduleWithCompFactories.componentFactories[0], 0, parentInjector);
                })
        })

}

shell.component.html

<ng-container #vc></ng-container>

如您所见,如果您的依赖项(模块使用者提供)将用于作为该模块一部分组件并且您使用compileModuleAndAllComponentsAsync方法,则组件将无法访问该依赖项,除非手动创建另一个注入器。

这是因为,从方法的名称可以看出,组件已经被编译,所以除了在模块中明确定义的那些之外,您不能动态添加其他依赖项。


如果模块内的组件依赖于提供的依赖项,您可以通过首先编译模块( compileModuleAsync )然后单独编译每个组件来实现(这听起来可能很乏味,但我可以向您保证,您会喜欢使用它东西)。 这样,他们将能够在运行时注入任何动态提供的依赖项和事件。

小部件.module.ts

@NgModule({
  imports: [
    CommonModule,
    // RouterModule.forChild([{ path: '', component: WidgetComponent }])
  ],
  declarations: [WidgetComponent],

  // No need to use this when using `compileModuleAndAllComponentsAsync`
  entryComponents: [WidgetComponent],
  providers: [
    {
      provide: 'widgets',
      useValue: [
        {
          name: 'widget1',
          component: WidgetComponent,
        },
      ],
    }
  ]
})
export class WidgetModule { }

shell.component.ts

ngOnInit () {
    const parentInjector = Injector.create({
        providers: [
            { provide: DYNAMIC_CONFIG, useValue: { message: 'CUSTOM VALUE PROVIDED BY THE CONSUME!' } }
        ],
        parent: this.inj
    });

    import('./widget/widget.module.ts')
        .then(m => {
            this.compiler.compileModuleAsync(m.WidgetModule)
                .then(factory => {
                    const module = factory.create(parentInjector);

                    const [firstWidget] = module.injector.get('widgets');

                    const componentFactory = module.componentFactoryResolver.resolveComponentFactory(firstWidget.component);

                    this.vc.createComponent(componentFactory);
                });
        })

}

现在,每次您想向模块添加另一个组件时,请确保将其添加到entryComponents组件数组,以便您可以使用module.injector.get()检索它们。

这是一个 StackBlitz示例

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM