@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();
}
}
但这行不通,客户永远不会得到设置:(
更新
以来,继承得到了适当的支持
原创
装饰器不被继承。它们需要直接应用于用作组件的 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.
即使在 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 装饰器上输入就可以正常工作...
我真的不明白对象绑定是如何工作的,所以如果有人能解释我是否可以在基 class 或更好的内部使用 @Input():装饰器和继承。 例如,如果每个表格都应该接收一个客户,我有一个基础 class:
export class AbstractCustomerForm{
@Input() customer;
...
}
然后我在实际组件中扩展这个 class:
export AwesomeCustomerForm extends AbstractCustomerForm implements OnInit{
ngOnInit(){
if(this.customer)
doSomething();
}
}
但这行不通,客户永远不会得到设置:(
更新
以来,继承得到了适当的支持原创
装饰器不被继承。它们需要直接应用于用作组件的 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.
即使在 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 装饰器上输入就可以正常工作...