尽管这个话题已经在其他类似文章中讨论过:

Dynamically loading a typescript class (reflection for typescript)

我找不到特定问题的答案。所以,请原谅我是否重复。

我正在尝试在Angular 2中创建一个非常简单的指令(使用Typescript),该指令允许动态添加或删除由Type表示的一组控件。例如,如果类型是:

class Stone{
  constructor(
  public nameOfStone?: string,
  public typeOfStone?: string
  ){}
}


用户界面将具有以下内容:

javascript -  typescript 和Angular 2反射-LMLPHP

我可以使用特定的Type(例如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类会有所帮助,但是没有任何疯狂的变化(导出类,尝试将此类称为window ['StoneComponent']。export_1 ['Stone'])有助于解决。我知道该组件在window组件下不直接可见,但是我不确定自己缺少什么。有替代的方法吗?我想念什么吗?请指教。

附注:我使用的是最新版本的Angular 2和Typescript(几天前我启动了此应用程序)。

最佳答案

您的代码的问题是定义顺序。

具体来说,类定义不会像函数定义那样被提升。棘手的部分是悬挂了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属性选择的。您可能需要考虑以下模式。

component-field-kinds.ts

export class Stone { ... }

export class Widget { ... }

export class Gizmo { ... }


通用组件

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。

关于javascript - typescript 和Angular 2反射,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36637124/

10-09 18:47