【问题标题】:Angular2: Loading modules dynamically from a given folderAngular2:从给定文件夹动态加载模块
【发布时间】:2017-02-23 16:31:55
【问题描述】:
app
 |-plugins
       |-plugin1
           |-config.json
           |-plugin1.module.ts
           |-plugin1.component.ts

       |-plugin2
           |-config.json
           |-plugin2.module.ts
           |-plugin2.component.ts

正如您在上面看到的,我有 "app/plugins" 文件夹,其中包含插件。每个插件将包含一个“config.json”文件,该文件将告诉一些配置,包括 -

{
   path: "feature1",
   moduleFile: "feature1.module",
   moduleClassName: "Feature1Module"
}

所以我想要的是,在应用程序引导之前,它会扫描 "app/plugins" 文件夹并加载所有插件配置,并延迟注册所有模块路由。对于上面的例子,路线将是

{
     path: "feature1",
     loadChildren: "app/plugins/plugin1/plugin1.module#Plugin1Module"
}

这样,我们可以将新插件拖放到插件文件夹中并刷新应用程序,我们新拖放的插件就会启动并运行。

有人知道我怎样才能做到这一点吗?

注意:我在 angular2 latest(2.1.0)

【问题讨论】:

  • 为什么不对每个功能使用NgModule
  • 我正在为每个功能使用 NgModule,但我想知道如何读取所有文件夹并读取配置,以便我可以懒惰地注册这些模块路由。
  • 我猜你必须编写一个 nodejs 脚本并手动生成代码。这不是 Angular 的事情......
  • 你搞定了吗?我正在考虑做类似的事情。

标签: angular typescript angular2-routing


【解决方案1】:

我正在寻找与您所描述的行为相同的行为,并且我想我已经找到了如何做到这一点,这要感谢这个 github 问题: Lazy loading components without Route

这是我编写的代码:plunker here

  • 首先:dynamic.module.ts,动态加载的模块及其组件

    import { Component, NgModule } from '@angular/core'
    
    @Component({
        selector: 'my-test',
        template: `<h1>html template of TestComponent from DynamicModule</h1>`
    })
    
    export class TestComponent { }
    
    @NgModule({
        declarations: [TestComponent],
        exports: [TestComponent]
    })
    
    export class DynamicModule { }
    
  • 第二个:这里是当你给它模块路径时动态加载模块的组件。

    import {
    Component, 
    ViewContainerRef,
    Compiler,
    ComponentFactory,
    ComponentFactoryResolver,
    ModuleWithComponentFactories,
    ComponentRef,
    ReflectiveInjector,
    SystemJsNgModuleLoader } from '@angular/core';
    
    class ModuleNode {
        modulePath: string;
        componentName: string;
    }
    
    @Component({
        moduleId: module.id,
        selector: 'widgetContainer',
        templateUrl: './widgetContainer.component.html'
    })
    
    export class WidgetContainerComponent {
        widgetConfig: string;
        module: ModuleNode;
        cmpRef: ComponentRef<any>;
    
    constructor(private widgetService: WidgetLoader,
        private viewref: ViewContainerRef,
        private resolver: ComponentFactoryResolver,
        private loader: SystemJsNgModuleLoader,
        private compiler: Compiler){}
    
    openWebApp(menu:any) {
        this.loader.load(menu.modulePath)  // load the module and its components
            .then((modFac) => {
                // the missing step, need to use Compiler to resolve the module's embedded components
                this.compiler.compileModuleAndAllComponentsAsync<any>(modFac.moduleType)
    
                    .then((factory: ModuleWithComponentFactories<any>) => {
                        return factory.componentFactories.find(x => x.componentType.name === menu.componentName);
                    })
                    .then(cmpFactory => {
    
                        // need to instantiate the Module so we can use it as the provider for the new component
                        let modRef = modFac.create(this.viewref.parentInjector);
                        this.cmpRef = this.viewref.createComponent(cmpFactory, 0, modRef.injector);
                        // done, now Module and main Component are known to NG2
    
                    });
            });
    }
    
    ngOnDestroy() {
        if (this.cmpRef) {
            this.cmpRef.destroy();
        }
    }
    

    }

你怎么看?它有帮助吗?非常感谢您的反馈。

【讨论】:

  • 如果您的 Angular 应用程序使用 AOT 部署,这是否有效?
  • @DouaBeri :不。不幸的是,这不适用于 AOT。由于 AOT 编译,我们不得不放弃这个。
  • 我希望我问过这个问题并且会接受它作为一个天才的答案,聪明的兄弟,js 聪明,非常感谢
  • Brillian,我们可以聊 5 分钟吗,skype--wikiwaleed2
猜你喜欢
  • 2017-01-10
  • 1970-01-01
  • 2022-12-16
  • 1970-01-01
  • 1970-01-01
  • 2016-03-26
  • 2017-08-27
  • 2016-03-29
  • 2013-03-25
相关资源
最近更新 更多