@Input等装饰器和继承

@Input and other decorators and inheritance

我真的不明白对象绑定是如何工作的,所以如果有人能解释我是否可以在基 class 或更好的内部使用 @Input():装饰器和继承。 例如,如果每个表格都应该接收一个客户,我有一个基础 class:

export class AbstractCustomerForm{

@Input() customer;
...
}

然后我在实际组件中扩展这个 class:

export AwesomeCustomerForm extends AbstractCustomerForm implements OnInit{
    ngOnInit(){

        if(this.customer)
            doSomething();

    }
}

但这行不通,客户永远不会得到设置:(

更新

2.3.0-rc.0

以来,继承得到了适当的支持

原创

装饰器不被继承。它们需要直接应用于用作组件的 class。 subclasses 上的装饰器将被忽略。我看到它提到 @Input()@Output() 正在工作,如果只有超级 class 有它们并且子 class 有 none.

我在这里找到了一个可能的解决方案:

https://medium.com/@ttemplier/angular2-decorators-and-class-inheritance-905921dbd1b7#.ca68alvcz

基本上,它创建了一个自定义装饰器,通过反射简单地合并了父装饰器和子装饰器。

实际上我无法让它在基于 angular-cli 的项目上运行。

我遵循的一个策略是这样的:

@Component({
    selector: 'my-component',
    template: `......`,
    inputs: MyAbstractComponent.genericInputs
})
export class MyComponent extends MyAbstractComponent {

    @Input() width: number = 200;
    ........
}

其中:

export abstract class MyAbstractComponent {
    public static genericInputs : string[] = ['base'];
    public base: String;
}

因此,MyComponent 将获得 base 以及 width 绑定。其实我觉得用反射还是有提升空间的

装饰器不能继承,但 class 可以。所以我的解决方案是:

@Component({selector: 'a')
class A {
  @Input() field;
}

@Component({selector: 'b', inputs: ['field']}
class B extends A {
}

我遇到了这个问题,只是想指出,从 Angular 2.3.0-rc.0 开始,这实际上是可能的。

Inheritance Semantics:

Decorators:

1) list the decorators of the class and its parents in the ancestor first order

2) only use the last decorator of each kind (e.g. @Component / ...)

Constructor parameters:

If a class inherits from a parent class and does not declare a constructor, it inherits the parent class constructor, and with it the parameter metadata of that parent class.

Lifecycle hooks:

Follow the normal class inheritance model, i.e. lifecycle hooks of parent classes will be called even if the method is not overwritten in the child class.

https://github.com/angular/angular/commit/f5c8e09

即使在 Angular 4.2.4 中,它在开发模式下也能正常工作。但是在进行产品构建时 (ng build -prod) 它失败了:

ERROR in Template parse errors:
Can't bind to 'step' since it isn't a known property of 'app-textarea-step'.
1. If 'app-textarea-step' is an Angular component and it has 'step' input, 
then verify that it is part of this module.
2. If 'app-textarea-step' is a Web Component then add 
'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to 
suppress this message.

我的组件看起来像:

abstract class StepComponent {
  @Input() step: BaseStep;
  @Output() next = new EventEmitter<string>();
  @Output() answer = new EventEmitter<Answer>();
}

abstract class SingleNextStepComponent extends StepComponent {

  onSubmit(answer: string) {
    // ConfirmStep heeft geen answer.
    if (answer) {
      this.answer.emit({ question: this.step.key, value: answer });
    }
    const step = this.step as SingleNextStep;
    this.next.emit(step.next);
  }
}

// Decorator inheritance works in standard build (ng build) but fails in production build (ng build -prod)
// Workaround: inputs element on @Component that contains the inputs.....
@Component({
  selector: 'app-textbox-step',
  templateUrl: './textbox-step.component.html',
  inputs: ['step']
})
export class TextboxStepComponent extends SingleNextStepComponent { }

@Component({
  selector: 'app-textarea-step',
  templateUrl: './textarea-step.component.html',
})
export class TextareaStepComponent extends SingleNextStepComponent { }

幸运的是,解决方法有效。添加到 TextBoxStepComponent 的输入 a 阻止了这个失败,掉落到下一个,尚未提供 'inputs'。

但是 'ng build' 不需要在 @Component 装饰器上输入就可以正常工作...