虽然这个主题已在其他帖子中讨论过:
Dynamically loading a typescript class (reflection for typescript)
我无法找到具体问题的答案。所以,请原谅我,如果这是重复的。
我正在尝试在Angular 2中创建一个非常简单的指令(使用Typescript),它允许动态添加或删除由Type表示的一组控件。例如,如果类型为:
class Stone{
constructor(
public nameOfStone?: string,
public typeOfStone?: string
){}
}
用户界面就像这样:
我能够使用特定类型(例如:Stone)。但是,鉴于该指令的目的只是添加这个动态添加/删除功能,我觉得参数化要创建的类型并将其用于不同的类型定义是有意义的。我在Component类中尝试过类似的东西:
import {Component} from 'angular2/core';
import {NgForm} from 'angular2/common';
import {ControlGroup, Control, FormBuilder, FORM_DIRECTIVES} from 'angular2/common'
@Component({
selector: 'stone-details',
templateUrl: '../stones/stone-details.component.html',
directives: [FORM_DIRECTIVES]
})
export class StoneComponent {
type = 'Stone';
Stones = new Array<Stone>();
addBtnClicked(){
let Stone = Object.create(window['Stone'].prototype);
//let Stone = new Stone('', '');
this.Stones.push(Stone);
}
removeBtnClicked(index: number){
if(index >= this.Stones.length){
alert('Not a valid index');
}else if(confirm('Remove this Stone?')){
this.Stones.splice(index, 1);
}
}
}
class Stone{
constructor(
public nameOfDeity?: string,
public typeOfDeity?: string
){}
}
当我使用注释行时
let Stone = new Stone('', '');
组件工作完美,但如果我使用
let Stone = Object.create(window['Stone'].prototype);
它似乎不起作用,我看到的错误是
angular2.dev.js:23941 ORIGINAL EXCEPTION: TypeError: Cannot read property 'prototype' of undefined
。
我最初认为导出Stone类会有所帮助,但没有一个疯狂的变体(导出类,尝试将类称为窗口['StoneComponent']。export_1 ['Stone'])帮助。我知道组件在窗口组件下不能直接看到,但我不确定我缺少什么。有没有另一种方法可以做到这一点?我错过了什么吗?请指教。
P.S:我正在使用最新版本的Angular 2和Typescript(我在几天后开始使用这个应用程序)。
答案 0 :(得分:1)
代码的问题是定义顺序。
具体来说,类定义不像 function 定义一样被提升。棘手的部分是类型 Stone
被提升,这是完全有效的,但值 Stone
(构造函数)不是。
要解决此问题,只需将Stone
的定义移到组件上方或将其提取到单独的模块中并导入它。
不要 尝试将其推送到全局变量,例如window
。这是一种非常糟糕的做法,会比人们想象的更快地导致错误和名称冲突。它也失去了模块的好处。
简而言之,您需要的是
class Stone {
constructor(
readonly nameOfDeity?: string,
readonly typeOfDeity?: string
) {}
}
export class StoneComponent {
kind = 'Stone';
stones: Stone[] = [];
addBtnClicked() {
const stone = new Stone();
this.stones.push(stone);
}
removeBtnClicked(index: number) {
if (index >= this.stones.length) {
alert('Not a valid index');
} else if (confirm('Remove this Stone?')){
this.stones.splice(index, 1);
}
}
}
<强>更新强>
因为在原始问题中,您声明这将是一个通用组件,您将拥有多个类,其中实际类由组件类的kind
属性选择。您可能需要考虑以下模式。
<强>组件场-kinds.ts 强>
export class Stone { ... }
export class Widget { ... }
export class Gizmo { ... }
<强>仿制component.ts 强>
import * as kinds from './component-field-kinds';
type Kind = keyof typeof kinds;
export class GenericComponent {
@Input() kind: Kind;
values: typeof kinds[Kind][] = [];
addBtnClicked() {
const value = new kinds[this.kind]();
this.values.push(value);
}
注意,对于它的价值,JavaScript,因此TypeScript没有动态类加载器这样的东西。这就是语言一直在运作的方式,整个结构都是一流的。
这不是Java。
答案 1 :(得分:0)
由于class是简单函数,您可以使用new func()
创建实例,但仍需要从外部代码传递func
。
我想最有效的解决方案如下:
export class StoneComponent<T> {
addBtnClicked(){
let item:T = <T>{}
this.items.push(item);
}
}
只要对象具有相同的属性集,类型就会匹配。