简体   繁体   English

Angular2 - 从模块动态加载组件

[英]Angular2 - Dynamically load component from module

in my angular app I have the following: 在我的角度应用程序中,我有以下内容:

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);
            });
    }
}

My sub-component declares providers and stuff, directives and pipes. 我的子组件声明了提供者和东西,指令和管道。

And now RC6 is out to break everything yet again. 而现在RC6又打破了一切。 Components can't declare directives and pipes, but they must be in the module where the component is declared. 组件不能声明指令和管道,但它们必须位于声明组件的模块中。 So I have to load with SystemJS not the component itself but the module. 所以我必须加载SystemJS而不是组件本身而是模块。 Ok, and then I should use 好的,然后我应该使用

return this._compiler.compileModuleAndAllComponentsAsync(type)

Fine, but how do I get a reference to the factory of this specific component? 很好,但是如何获得该特定组件的工厂参考? That factory is all I need, the placeholderRef wants it in its createComponent method, right? 那个工厂就是我所需要的,placeholderRef想要它的createComponent方法,对吧?

I tried to dig into the angular2 source code from github but it's quite vast, I should try from VS Code or something, with intellisense, but I'm lazy...and I should read this stuff from documentation, which is quite lackluster in angular.io for this particular argument, which is lazy loading of components and modules WITHOUT the router. 我试图从github挖掘angular2源代码,但是它非常庞大,我应该尝试使用VS Code或者其他东西,使用intellisense,但我很懒...我应该从文档中读取这些内容,这是相当乏味的angular.io这个特定的参数,它是没有路由器的组件和模块的延迟加载。

Any help is appreciated, I think the solution is simple to apply but hard to find without official documentation. 感谢任何帮助,我认为解决方案很容易应用,但没有官方文档很难找到。

Update: 更新:

If you want to use it together with aot compilation you should manually provide Compiler like 如果你想将它与编译一起使用,你应该手动提供编译器

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

Example

Old version 旧版本

It might help you: 它可能会帮助你:

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

See also 也可以看看

Based on yurzui's answer I've come to the following code: 根据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);
            });
    }
}

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

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