我在每个组件上重复了几个组件装饰声明,例如:
@Component({
moduleId: module.id,
directives: [BootstrapInputDirective]
})如何将这些声明应用于所有组件?我尝试用这个装饰器创建一个基类,并用它扩展其他类,但是基类装饰似乎不适用于派生类。
发布于 2016-04-25 10:04:45
@Component是个装潢师。这意味着它通过添加一些利用反射元数据库的元数据来处理它应用的类。Angular2不查找父类上的元数据。因此,不可能在父类上使用装饰器。
关于BootstrapInputDirective指令,您可以将其定义为平台指令。这样,您就不需要每次都将它包含到组件的directives属性中。
以下是一个示例:
(...)
import {PLATFORM_DIRECTIVES} from 'angular2/core';
bootstrap(AppComponent, [
provide(PLATFORM_DIRECTIVES, {useValue: [BootstrapInputDirective], multi:true})
]);编辑
是的,您可以创建自己的装饰器来实现这一点。以下是一个示例:
export function CustomComponent(annotation: any) {
return function (target: Function) {
var parentTarget = annotation.parent;
delete annotation.parent;
var parentAnnotations = Reflect.getMetadata('annotations', parentTarget);
var parentAnnotation = parentAnnotations[0];
Object.keys(parentAnnotation).forEach(key => {
if (isPresent(parentAnnotation[key])) {
annotation[key] = parentAnnotation[key];
}
});
var metadata = new ComponentMetadata(annotation);
Reflect.defineMetadata('annotations', [ metadata ], target);
}
}将以这种方式使用CustomComponent装饰器:
@Component({
template: `
<div>Test</div>
`
})
export class AbstractComponent {
}
@CustomComponent({
selector: 'sub',
parent: AbstractComponent
})
export class SubComponent extends AbstractComponent {
}注意,我们需要提供父类作为装饰器的输入,因为我们可以在装饰器中找到这个父类。只有这个类的原型,但是元数据通过反射元数据应用到类上,而不是应用到相关的原型上。
Edit2
感谢Nitzam的回答,这里有一个改进:
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])) {
annotation[key] = parentAnnotation[key];
}
});
var metadata = new ComponentMetadata(annotation);
Reflect.defineMetadata('annotations', [ metadata ], target);
}
}不需要parent属性引用自定义装饰器中的父类。
参见这个plunkr:https://plnkr.co/edit/ks1iK41sIBFlYDb4aTHG?p=preview。
见这个问题:
发布于 2017-04-27 18:31:48
以防万一您正在寻找isPresent函数:
function isPresent(obj: any): boolean { return obj !== undefined && obj !== null; }
发布于 2016-12-29 12:37:22
在最新版本的角,ComponentMetadata类是不可用的,正如少数成员在这里指出的。
这就是我如何实现CustomComponent使其工作的方式:
export function CustomComponent(annotation: any) {
return function (target: Function) {
let parentTarget = Object.getPrototypeOf(target.prototype).constructor;
let parentAnnotations = Reflect.getOwnMetadata('annotations', parentTarget);
let parentAnnotation = parentAnnotations[0];
Object.keys(annotation).forEach(key => {
parentAnnotation[key] = annotation[key];
});
};
}希望能帮上忙!
编辑:前面的代码块,即使它工作,它覆盖扩展类的原始元数据。在下面找到它的增强版本,允许您在不修改基类的情况下拥有多个继承和重写。
export function ExtendComponent(annotation: any) {
return function (target: Function) {
let currentTarget = target.prototype.constructor;
let parentTarget = Object.getPrototypeOf(target.prototype).constructor;
let parentAnnotations = Reflect.getOwnMetadata('annotations', parentTarget);
Reflect.defineMetadata('annotations', [Object.create(parentAnnotations[0])], currentTarget);
let currentAnnotations = Reflect.getOwnMetadata('annotations', currentTarget);
Object.keys(annotation).forEach(key => {
currentAnnotations[0][key] = annotation[key];
});
};}
https://stackoverflow.com/questions/36837421
复制相似问题