Angular 动态组件 AOT 问题 [英] Angular Dynamic Components AOT Issue

查看:30
本文介绍了Angular 动态组件 AOT 问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于一些业务逻辑,我必须读取动态组件(EntryComponents)的元数据.

要读取元数据,以下是我的方法.

  1. 使用ComponentFactoryResolver
  2. 读取模块的所有组件
  3. 使用组件名称和特定方法过滤掉类
  4. 创建组件并读取数据
  5. 销毁组件.

.

const factory = Array.from

但是在使用 ng build --prod 构建项目之后.工厂名称如下

如您所见,首先我在何处以及为什么收到错误 IDK.

其次,工厂类名称相同.因此同一个动态组件被加载了 10 次(因为有 10 个动态组件).

这里是 NgModule

@NgModule({声明: [DynamicComponentLoaderDirective,ContactsCreatedByDayComponent,报表骨架组件,销售业绩组件,TopPersonasComponent,联系人概览组件,公司收入转换组件,关闭的公司转换组件,平均时间关闭组件,平均时间响应组件,ContactLifecyclePipelineComponent],进口:[通用模块,垫按钮模块,MatProgressSpinnerModule,图表模块],entryComponents: [ContactsCreatedByDayComponent, SalesPerformanceComponent, TopPersonasComponent, ContactsOverviewComponent, CompaniesRevenueConversionComponent, ClosedCompaniesConversionComponent, AverageTimeCloseComponent, AverageTimeResponseComponent, ContactLifecyclePipelineComponent],导出:[DynamicComponentLoaderDirective、ReportSkeletonComponent、TopPersonasComponent、ContactsOverviewComponent、 CompaniesRevenueConversionComponent、ClosedCompaniesConversionComponent、AverageTimeCloseComponent、AverageTimeResponseComponent、ContactLifecyclePipelineComponent]、提供者:[DashboardReportService]})导出类 DashboardSharedModule {}

我真的不知道为什么会发生这种情况.有人可以帮我指明正确的方向吗?

解决方案

--prod 标志将缩小应用到您的代码,这会导致...constructor.name"以类似于a.name"的形式结束.这是你的问题的原因.根本问题是您的代码不适用于缩小,您应该对其进行调整.您可以将构建配置为不优化(当前 angular 版本中的 angular.json),但缩小有其意义,因此您应该尝试找到一种方法以不同的方式提供类名,例如使用包含名称的字符串函数参数,您可以执行此操作.将数据传递给 entryComponents 的另一种实现,您可以在 Angular Material 中进行比较,MatDialogs 实际上是 entryComponents,它获取 MAT_DIALOG_DATA,您可以通过注入以您想要的方式指定它:https://material.angular.io/components/dialog.

Due to some business logic, I have to read the meta data of dynamic components(EntryComponents).

To read the meta data, following is my approach.

  1. Read all components of a module using ComponentFactoryResolver
  2. Filter out classes using Component name and specific method
  3. Create the component and read the data
  4. Destroy the component.

.

const factories = Array.from<any>(this.resolver['_factories'].keys());
console.log(factories); // Logging all the factories

factories.forEach(element => {
  if (element.prototype.registerReportCard) { // checking if this is dynamic component. Because dynamic component will have registerReportCard method in it
    temp.push(element.prototype.constructor.name); // if this is my dynamic component, push the name into another array "tmp".
  }
});

temp.forEach(componentName => { // stored component name from above
    const factoryClass = factories.find( // finding that component which have registerReportCard  method and has name same as iterator.
      item =>
        item.prototype.registerReportCard &&
        item.prototype.constructor.name === componentName
    );
    // component found, obviously.
    const component = this.resolver
      .resolveComponentFactory(factoryClass)
      .create(this.createInjector()); // creating the component and passing in the injector.

    console.log('component', component);

    const componentMeta = component.instance[
      'componentMeta'
    ] as ReportComponentMetaInterface; // Reading the DATA which i need.


    component.destroy(); // destroying the component after reading the data.
  });

createInjector() {
    const staticProvider = [{ provide: [], useValue: '' }];

    return Injector.create(staticProvider);
 }

THE PROBLEM

During development, factories names are working fine and are same as the dynamic component class.

But after building the project using ng build --prod. The factories names are as follows

As you can see, first im getting an error IDK where and why.

Secondly, the factories class names are same. Hence same dynamic component is being loaded 10 times (because there are 10 dynamic components).

Here is the NgModule

@NgModule({


 declarations: [
    DynamicComponentLoaderDirective,
    ContactsCreatedByDayComponent,
    ReportSkeletonComponent,
    SalesPerformanceComponent,
    TopPersonasComponent,
    ContactsOverviewComponent,
    CompaniesRevenueConversionComponent,
    ClosedCompaniesConversionComponent,
    AverageTimeCloseComponent,
    AverageTimeResponseComponent,
    ContactLifecyclePipelineComponent
  ],
  imports: [
    CommonModule,
    MatButtonModule,
    MatProgressSpinnerModule,
    ChartsModule
  ],
  entryComponents: [ContactsCreatedByDayComponent, SalesPerformanceComponent, TopPersonasComponent , ContactsOverviewComponent, CompaniesRevenueConversionComponent, ClosedCompaniesConversionComponent, AverageTimeCloseComponent, AverageTimeResponseComponent, ContactLifecyclePipelineComponent],
  exports: [DynamicComponentLoaderDirective, ReportSkeletonComponent, TopPersonasComponent, ContactsOverviewComponent, CompaniesRevenueConversionComponent, ClosedCompaniesConversionComponent, AverageTimeCloseComponent, AverageTimeResponseComponent, ContactLifecyclePipelineComponent],
  providers: [DashboardReportService]
})
export class DashboardSharedModule {}

I really dont know why is this happening. Can someone please put me in right direction?

解决方案

The --prod flag applies minification to your code which causes "...constructor.name" to end up as something like "a.name". This is the cause of your problem. The root problem is that your code won't work with minification and you should adapt it. You can configure your build not to optimize (angular.json in the current angular version), but minification has its sense, so you should try to find a way to provide the class name differently, e.g. with a string function param containing the name you can do that. Another implementation for passing data to entryComponents you can maybe compare at Angular Material, the MatDialogs are actually entryComponents which get MAT_DIALOG_DATA which you can specify in the way you want by injection: https://material.angular.io/components/dialog.

这篇关于Angular 动态组件 AOT 问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆