我想为Angular 2中已经部署的一些组件创建扩展,而不必几乎完全重写它们,因为基础组件可能会发生更改,并希望这些更改也反映在其派生组件中。
我创建了这个简单的例子,试图更好地解释我的问题:
使用以下基本组件app/base-panel.component.ts
import {Component, Input} from 'angular2/core';
@Component({
selector: 'base-panel',
template: '<div class="panel" [style.background-color]="color" (click)="onClick($event)">{{content}}</div>',
styles: [`
.panel{
padding: 50px;
}
`]
})
export class BasePanelComponent {
@Input() content: string;
color: string = "red";
onClick(event){
console.log("Click color: " + this.color);
}
}
是否要创建另一个仅更改派生组件的派生组件,例如,更改示例颜色app/my-panel.component.ts
中的基本组件行为
import {Component} from 'angular2/core';
import {BasePanelComponent} from './base-panel.component'
@Component({
selector: 'my-panel',
template: '<div class="panel" [style.background-color]="color" (click)="onClick($event)">{{content}}</div>',
styles: [`
.panel{
padding: 50px;
}
`]
})
export class MyPanelComponent extends BasePanelComponent{
constructor() {
super();
this.color = "blue";
}
}
Complete working example in Plunker
注:很明显,这个例子很简单,可以解决,否则不需要使用继承,但它只是为了说明真正的问题。
正如您在派生组件app/my-panel.component.ts
的实现中看到的那样,大部分实现都是重复的,真正继承的单个部分是class
BasePanelComponent
,但@Component
基本上必须完全重复,而不仅仅是像selector: 'my-panel'
那样完全重复更改部分。
是否有某种方法可以完全继承组件Angular2,继承标记/注释的class
定义,例如@Component
编辑1-功能请求
Feature request angular2已添加到GitHub上的项目:Extend/Inherit angular2 components annotations #7968
编辑2-已关闭的请求
的请求被关闭了,for this reason,这个简单的不知道如何合并的装饰器就会被提出。让我们别无选择。所以我的观点是quoted in the Issue。
发布于 2016-06-28 21:10:29
替代解决方案:
This answer of Thierry Templier is an alternative way to get around the problem.
在提了几个问题之后,我得到了下面的工作示例,它满足了我的期望,作为这个问题中提到的继承限制的替代方案:
1-创建自定义装饰器:
export function CustomComponent(annotation: any) {
return function (target: Function) {
var parentTarget = Object.getPrototypeOf(target.prototype).constructor;
var parentAnnotations = Reflect.getMetadata('annotations', parentTarget);
var parentAnnotation = parentAnnotations[0];
Object.keys(parentAnnotation).forEach(key => {
if (isPresent(parentAnnotation[key])) {
// verify is annotation typeof function
if(typeof annotation[key] === 'function'){
annotation[key] = annotation[key].call(this, parentAnnotation[key]);
}else if(
// force override in annotation base
!isPresent(annotation[key])
){
annotation[key] = parentAnnotation[key];
}
}
});
var metadata = new Component(annotation);
Reflect.defineMetadata('annotations', [ metadata ], target);
}
}
2-带有@Component装饰器的基础组件:
@Component({
// create seletor base for test override property
selector: 'master',
template: `
<div>Test</div>
`
})
export class AbstractComponent {
}
带有@CustomComponent装饰器的3- Sub组件:
@CustomComponent({
// override property annotation
//selector: 'sub',
selector: (parentSelector) => { return parentSelector + 'sub'}
})
export class SubComponent extends AbstractComponent {
constructor() {
}
}
发布于 2016-12-27 22:05:34
Angular 2版本2.3刚刚发布,它包含了本机组件继承。看起来你可以继承和重写任何你想要的东西,除了模板和样式。一些参考资料:
发布于 2019-05-13 17:04:04
让我们了解一下Angular组件继承系统的一些关键限制和特性。
组件只继承类逻辑:
@Component装饰器中的所有元数据都不是inherited.
记住这些特性是非常重要的,所以让我们分别研究它们。
组件只继承类逻辑
当你继承一个组件时,里面的所有逻辑都是同样继承的。值得注意的是,只有公共成员才会被继承,因为私有成员只能在实现它们的类中访问。
@Component修饰器中的所有元数据都不是继承的
没有元数据被继承的事实一开始可能看起来是违反直觉的,但如果你考虑一下这一点,它实际上是完全有意义的。如果你继承一个组件,比如说( ComponentA ),你不会想要继承的ComponentA的选择器来替换继承的类ComponentB的选择器。对于template/templateUrl和style/styleUrl也是如此。
组件的@Input和@Output属性是继承的
这是我非常喜欢Angular中组件继承的另一个特性。简单地说,只要你有一个自定义的@Input和@Output属性,这些属性就会被继承。
不是继承的组件生命周期
这部分不是很明显,特别是对于那些没有广泛使用OOP原则的人来说。例如,假设您有ComponentA,它实现了Angular的许多生命周期钩子中的一个,比如OnInit。如果您创建了ComponentB并继承了ComponentA,那么ComponentA的OnInit生命周期只有在您显式地调用它之后才会触发,即使您确实拥有ComponentB的这个OnInit生命周期也是如此。
调用超级/基本组件方法
为了从super获得ngOnInit()方法,我们需要使用ComponentA关键字,然后调用我们需要的方法,在本例中是ngOnInit。super关键字指的是从其继承的组件的实例,在本例中为ComponentA。
https://stackoverflow.com/questions/36475626
复制相似问题