【问题标题】:Resolve Type<> of component from string in angular2从 angular2 中的字符串解析组件的类型<>
【发布时间】:2020-03-03 01:09:04
【问题描述】:

是否可以从string 值获取组件类型(Type&lt;T&gt;)?喜欢:

let typeStr: string = 'MyComponent';
let type: any = resolveType(typeStr); // actual type

【问题讨论】:

  • 为什么需要这个?我可以知道吗
  • 我做了一个指令,它根据提供的类型动态创建组件。目前我必须在父组件中声明一个变量并将其值分配给所需的类型,然后将此值绑定到我在 html 布局中的指令。我想摆脱这个,只需将一个字符串传递给指令。
  • 我想说在一个模块中有一个服务,它包含一个注册的 cmoponents 数组 - 类型和选择器。使用此服务通过选择器查找类型并在您的视图中动态呈现它。如上例所示,您将无法获得基于字符串的类型。您还可以使用 Angular 的内部注册组件列表,但创建自己的服务会给您带来灵活性。
  • 也许有办法在模板中创建一个变量呢?喜欢&lt;button createComponent='let type = MyComponent'&gt;Create&lt;/button&gt;
  • type 是什么意思?您想根据其名称获取对 MyComponent 类的引用吗?

标签: angular typescript


【解决方案1】:

如果不为您的课程维护一个“注册表”,您将无法做到这一点。

interface Component { }

type ComponentClass = { new (): Component };

const REGISTRY = new Map<string, ComponentClass>();

function getTypeFor(name: string): ComponentClass {
    return REGISTRY.get(name);
}

至于如何向这个REGISTRY添加条目,你有几个选择,这里有两个:

(1) 在每个类定义后手动添加:

class ComponentA implements Component { ... }
REGISTRY.set("ComponentA", ComponentA);

或者为它创建一个函数:

function register(cls: ComponentClass): void {
    REGISTRY.set(cls.name, cls);
}

class ComponentA implements Component { ... }
register(ComponentA);

(2) 使用装饰器:
只需将上面的register 函数用作装饰器即可:

@register
class ComponentA implements Component { ... }

【讨论】:

  • 你有这个工作的例子吗?我无法理解如何在实际项目中将上述第一个代码段分成不同的文件。
  • @nmy 我没有任何东西,但这段代码曾经可以工作。您对此有什么问题?
  • 我通过导出ComponentClass 类型和getTypeFor 得到了这项工作。我也通过导出 register 使用了装饰器方法。那是对的吗? Component 应该是一个接口,我们不能为此使用一个类吗?
  • 当我在我的项目中实现这个时,我不得不面对另一个问题。我的组件有构造函数,它们使用不同的输入参数。然后编译器说我不能使用 register 装饰器。因为该组件与ComponentClass 不兼容。您对如何处理有任何想法吗?
  • @nmy 尝试将接口类型作为参数传递给注册函数。像这样:function register(ci: Component): void 然后在寄存器函数里面做这样的事情:let cls = ci as ComponentClass; 希望对你有帮助。
【解决方案2】:

以防万一有人像我一样偶然发现这个问题。无需维护注册表即可。

全部功劳归yurzui for his solution

只是那里的一个副本:

import { Type } from '@angular/core';

@Input() comp: string;
...
const factories = Array.from(this.resolver['_factories'].keys());
const factoryClass = <Type<any>>factories.find((x: any) => x.name === this.comp);
const factory = this.resolver.resolveComponentFactory(factoryClass);
const compRef = this.vcRef.createComponent(factory);

【讨论】:

  • 仅供参考,这在 Angular 9 中不再适用,因为他们从 CFR 中删除了 _factories。也就是说,无论如何最好远离私人道具!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-05
  • 1970-01-01
  • 1970-01-01
  • 2021-04-24
  • 1970-01-01
  • 1970-01-01
  • 2016-01-06
相关资源
最近更新 更多