首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Typescript & Angular 2反射

Typescript & Angular 2反射
EN

Stack Overflow用户
提问于 2016-04-15 10:09:48
回答 2查看 9.6K关注 0票数 1

虽然这个话题已经在其他类似的帖子中讨论过了:

Dynamically loading a typescript class (reflection for typescript)

我无法找到我的特定问题的答案。所以,如果这是重复的,请原谅。

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

代码语言:javascript
复制
class Stone{
  constructor(
  public nameOfStone?: string,
  public typeOfStone?: string
  ){}
}

UI应该是这样的:

我可以使用一个特定的类型(例如: Stone)来让它工作。但是,考虑到该指令的目标只是添加这个动态添加/删除功能,我觉得将要创建的类型参数化并将其用于不同的类型定义是有意义的。我在Component类中尝试了类似这样的东西:

代码语言:javascript
复制
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的最新版本(我在几天前启动了这个应用程序)。

EN

回答 2

Stack Overflow用户

发布于 2017-02-27 10:59:01

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

具体地说,类定义不像函数定义那样被提升。棘手的部分是类型Stone被提升了,这是完全有效的,但是值Stone (构造函数)却不是。

要解决此问题,只需将Stone的定义移到组件上方,或者将其提取到单独的模块中并导入。

window说,试图将其放入全局变量中。这是一种非常糟糕的做法,并且将导致bug和名称冲突的速度比人们想象的更快。它还破坏了模块的好处。

简而言之,您需要的是

代码语言:javascript
复制
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);
    }
  }
}

更新,因为在原始问题中,您声明这将是一个通用组件,并且您将拥有多个类,其中实际的类是由component类的kind属性选择的。您可能需要考虑以下模式。

component-field-kinds.ts

代码语言:javascript
复制
export class Stone { ... }

export class Widget { ... }

export class Gizmo { ... }

generic-component.ts

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2016-04-15 16:40:50

因为类是简单函数,所以可以使用new func()创建实例,但仍然需要从外部代码传递func

我想最有效的解决方案是:

代码语言:javascript
复制
export class StoneComponent<T> {
  addBtnClicked(){
    let item:T = <T>{}
    this.items.push(item);
  }
}

只要对象具有相同的属性集,类型就会匹配。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36637124

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档