【问题标题】:Angular2 - Dynamically load component from moduleAngular2 - 从模块动态加载组件
【发布时间】:2017-01-10 20:30:25
【问题描述】:

在我的 Angular 应用程序中,我有以下内容:

export class MyComponent {
    subcompPath = "path-to-subcomp#SubcompClassName";
    @ViewChild("placeholder", { read: ViewComponentRef }) placeholderRef: ViewComponentRef;

/* Constructor where Compiler, ComponentFactoryResolver are injected */

    loadSubcomponent() {
        let [path, componentName] = this.subcompPath.split("#");
        (<any>window).System.import(path)
            .then((module: any) => module[componentName])
            .then((type: any) => {
                return this._compiler.compileComponentAsync(type)
            })
            .then((factory: any) => {
                let componentRef = this.placeholderRef.createComponent(factory, 0);
            });
    }
}

我的子组件声明提供者和东西、指令和管道。

现在 RC6 再次打破一切。组件不能声明指令和管道,但它们必须在声明组件的模块中。 所以我必须加载 SystemJS 而不是组件本身,而是模块。 好的,然后我应该使用

return this._compiler.compileModuleAndAllComponentsAsync(type)

很好,但是我如何获得对这个特定组件的工厂的引用?我只需要那个工厂,placeholderRef 想要它的 createComponent 方法,对吧?

我试图从 github 挖掘 angular2 源代码,但它非常庞大,我应该尝试使用 VS Code 或其他东西,使用智能感知,但我很懒......我应该从文档中阅读这些东西,即angular.io 中对于这个特定参数相当乏味,这是在没有路由器的情况下延迟加载组件和模块。

感谢任何帮助,我认为该解决方案易于应用,但如果没有官方文档则很难找到。

【问题讨论】:

    标签: dynamic angular typescript


    【解决方案1】:

    更新:

    如果你想和aot编译一起使用你应该手动提供Compiler like

    export function createJitCompiler () {
       return new JitCompilerFactory([{useDebug: false, useJit: true}]).createCompiler();
    }
    ...
    providers: [
      { provide: Compiler, useFactory: createJitCompiler}
    ],
    

    Example

    旧版本

    也许对你有帮助:

    this.compiler.compileModuleAndAllComponentsAsync(DynamicModule)
          .then(({moduleFactory, componentFactories}) => {
            const compFactory = componentFactories
               .find(x => x.componentType === DynamicComponent);
            const cmpRef = this.placeholderRef.createComponent(compFactory, 0);
    

    另见

    【讨论】:

    • Thx @yurzui 为指针,但我的问题的解决方案实际上是:const compFactory = moduleWithComponentFactory.componentFactories .find(x =&gt; x.componentType.name === componentName); 因为我想通过字符串动态查找组件,因为我在开发过程中不知道类型,并且我不是动态创建类型...我知道类型名称,因为该类型已经在应用程序的插件中某处开发
    【解决方案2】:

    根据 yurzui 的回答,我得出以下代码:

    export class MyComponent {
        subcompPath = "path-to-subcompMODULE#SubcompClassName";
        @ViewChild("placeholder", { read: ViewComponentRef }) placeholderRef: ViewComponentRef;
    
        /* Constructor where Compiler, ComponentFactoryResolver are injected */
    
        loadSubcomponent() {
            let [modulePath, componentName] = this.subcompPath.split("#");
            (<any>window).System.import(modulePath)
                .then((module: any) => module["default"])  // Or pass the module class name too
                .then((type: any) => {
                    return this._compiler.compileModuleAndAllComponentsAsync(type)
                })
                .then((moduleWithFactories: ModuleWithComponentFactories<any>) => {
                    const factory = moduleWithFactories.componentFactories.find(x => x.componentType.name === componentName); // Crucial: componentType.name, not componentType!!
                    let componentRef = this.placeholderRef.createComponent(factory, 0);
                });
        }
    }
    

    【讨论】:

    • 谢谢你!您能否举一个 path-to-subcompMODULE#SubcompClassName 的示例,因为我正在尝试从当前工作的 NPM 模块中延迟加载模块:-stackoverflow.com/questions/39898417/…
    • ViewComponentRef 还是 ViewContainerRef?? ViewComponentRef 在 Angular 6 中不可用
    • ViewContainerRef... 这是我的错字
    • 什么是(窗口)?
    猜你喜欢
    • 1970-01-01
    • 2017-02-23
    • 2017-08-27
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多