Javascript Typescript和Angular:为组件类键入字符串

Javascript Typescript和Angular:为组件类键入字符串,javascript,angular,typescript,Javascript,Angular,Typescript,函数通过字符串传递组件的名称,但我需要它是实际的组件类: 当前:“MyComponent” 需要:MyComponent 我需要“转换”它,使其正确通过。我有一个ngFor,可以输出值,我正在尝试使用管道来转换它: <div id="grid"> <gridster [options]="options"> <gridster-item [item]="item" *ngFor="let item of dashboard;let i = index

函数通过字符串传递组件的名称,但我需要它是实际的组件类:

当前:“MyComponent” 需要:MyComponent

我需要“转换”它,使其正确通过。我有一个
ngFor
,可以输出值,我正在尝试使用管道来转换它:

<div id="grid">
    <gridster [options]="options">
    <gridster-item [item]="item" *ngFor="let item of dashboard;let i = index;">
      <div class="grid-header drag-handle">
        <span class="handle-icon"><i class="material-icons">open_with</i></span>
        <span class="close-icon" (click)="removePanel(item)"><i class="material-icons">close</i></span>
      </div>
      <div class="grid-content">
        <ndc-dynamic [ndcDynamicComponent]="item.viewType | dynamicComponent"></ndc-dynamic>
      </div>
    </gridster-item>
  </gridster>
</div>

我这样做很简单:

我创建了一个
views.ts
,将所有视图导出到我的视图目录的根目录下。然后在使用管道的目录中,我使用以下方法导入了
视图

import*作为来自“../../views/views”的视图


然后在我的
transform
方法中,我
返回视图[值]
其中
value
是从我的模板中拉入的字符串。

您需要手动创建字符串值和组件之间的映射。组件实际上是命名函数,在编译用于生产时,可以将其最小化为更短的变量名

import ComponentA from '../views/ComponentA'; 
import ComponentB from '../views/ComponentA';

const componentMap = {
    'ComponentA': ComponentA,
    'ComponentB': ComponentB
};

@Pipe({name: 'dynamicComponent'})
export class DynamicComponentPipe implements PipeTransform {
   transform(value: string): any {
       if(componentMap[value]) {
          return componentMap[value];
       }
       throw new Error(`${componentMap} component was not found`);
   }
}
更新:

在运行时使用组件名称的问题在于,可以将其最小化为一个较小的变量名用于生产。因此,当
MyComponent
被重命名为
a12
时,执行类似于
views['MyComponent']
的操作将不起作用

另一种方法是使用组件的选择器字符串值来选择组件。Angular中的每个组件都必须是唯一的选择器字符串。所以这是一个安全值,可以用作密钥

您可以通过
\uuuu annotations\uuu
属性访问(至少在Angular 5中)组件的元数据。此属性是包含元数据的数组

因此,您可以尝试以下方法:

import * as views from '../views';

@Pipe({name: 'dynamicComponent'})
export class DynamicComponentPipe implements PipeTransform {
   transform(value: string): any {
       const view = views.filter((component)=>component['__annotations__'][0]['selector'] === value));
       if(view) {
          return view;
       }
       throw new Error(`A component with selector "${value}" was not found`);
   }
}

此外,通过直接访问
ngModule
并迭代所有组件以找到匹配的选择器,您可以不再需要
views
文件。模块将具有相同的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu注释属性。

可能会检查一下,我对angular2是个新手,但我还没有完全掌握如何将其与我的
管道
联系起来。当JavaScript最小化且函数名缩短时,这不会在生产中出现中断。我将使用'_(ツ)_/''我正在通过使用
export
将可能的组件放入一个
ts
文件中,然后使用“../../views/views”中的
import*作为视图将它们导入到我的
pipe
文件中;
这会返回一个已经包含键值对的数组。我不能继续使用它吗?仅供参考,我不是说你不知道你错了。只需询问是否可以从上面的导入中使用
视图
,因为它已经是一个数组,并且
视图[值]
返回与上面相同的内容。我认为
视图
中的键将是生产中的最小化版本。只需运行
控制台.log(视图)
从生产构建中查看我是否正确。我看到了问题所在。当其他人开始在此系统中工作时,列出管道文件中的每个组件可能会有点繁重。
视图
目录中的
视图.ts
文件用于提供单个导出点。您建议如何解决此问题?@dcp3450将字符串值赋给
项。viewType
?您可以控制这些值是什么吗?
import * as views from '../views';

@Pipe({name: 'dynamicComponent'})
export class DynamicComponentPipe implements PipeTransform {
   transform(value: string): any {
       const view = views.filter((component)=>component['__annotations__'][0]['selector'] === value));
       if(view) {
          return view;
       }
       throw new Error(`A component with selector "${value}" was not found`);
   }
}