我真的不明白对象绑定是如何工作的,所以如果有人可以解释我是否可以在基类中使用@Input(),或者更好的是:装饰器和继承。 例如,如果每个表单都应该收到一个客户,我有一个基类:
export class AbstractCustomerForm{
@Input() customer;
...
}
然后我在实际组件中扩展了这个类:
export AwesomeCustomerForm extends AbstractCustomerForm implements OnInit{
ngOnInit(){
if(this.customer)
doSomething();
}
}
但这行不通,客户永远不会被设置:(
更新
从 2.3.0-rc.0 开始正确支持继承
源语言
装饰器不是继承的。它们需要直接应用于用作组件的类。子类上的修饰符将被忽略。我看到有人提到,如果只有超类有它们而子类没有,那么@Input()
或@Output()
都在工作。
- https://github.com/angular/angular/issues/5794
- https://github.com/angular/angular/issues/5415
- https://github.com/angular/angular/issues/7191
我遵循的一种策略是这样的:
@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
绑定。事实上,我认为使用反思仍有改进的余地。
即使在 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 的输入已防止此输入失败,跌至下一个尚未提供"输入"的输入。
但是"ng build"工作正常,不需要在@Component装饰器上输入......
我遇到了这个问题,只是想指出,从 Angular 2.3.0-rc.0 开始,这实际上是可能的。
继承语义:
装饰:
1)按祖先第一顺序列出类的装饰器及其父级
2)仅使用每种装饰器中的最后一个装饰器(例如@Component/...)
构造函数参数:
如果类继承自父类并且不声明 一个构造函数,它继承了父类构造函数, 以及该父类的参数元数据。
生命周期钩子:
遵循正常的类继承模型, 即将调用父类的生命周期钩子 即使该方法未在子类中被覆盖。
https://github.com/angular/angular/commit/f5c8e09
我在这里找到了一个可能的解决方案:
https://medium.com/@ttemplier/angular2-decorators-and-class-inheritance-905921dbd1b7#.ca68alvcz
基本上,它创建了一个自定义装饰器,该装饰器通过反射简单地合并父装饰器和子装饰器。
实际上,我无法让它适用于基于angular-cli的项目。
装饰器不是继承的,但类是继承的。所以我的解决方案是这样的:
@Component({selector: 'a')
class A {
@Input() field;
}
@Component({selector: 'b', inputs: ['field']}
class B extends A {
}