使用基类装饰器扩展组件装饰器 [英] Extending component decorator with base class decorator

查看:33
本文介绍了使用基类装饰器扩展组件装饰器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有几个组件装饰器声明,我在每个组件上重复这些声明,例如:

I have several component decorator declarations that I repeat on every component, for example:

@Component({
    moduleId: module.id,
    directives: [BootstrapInputDirective]
})

如何将这些声明应用于我的所有组件?我试图用这个装饰器创建一个基类并用它扩展其他类,但基类装饰似乎不适用于派生类.

How can I apply these declarations to all my components? I tried to create a base class with this decorator and extend other classes with it but base class decorations doesn't seem to apply to derivative classes.

推荐答案

@Component 是一个装饰器.这意味着它通过添加一些利用反射元数据库的元数据来处理它所应用的类.Angular2 不会在父类上查找元数据.因此,不可能在父类上使用装饰器.

@Component is a decorator. This means that it handles the class it applies on by adding some metadata data leveraging the reflect-metadata library. Angular2 doesn't look for metadata on parent classes. For this reason, it's not possible to use decorators on parent classes.

关于 BootstrapInputDirective 指令,您可以将其定义为平台指令.这样您就不需要每次都将它包含到组件的 directives 属性中.

Regarding the BootstrapInputDirective directive, you could define it as a platform one. This way you wouldn't need to include it each time into the directives attribute of your components.

这是一个示例:

(...)
import {PLATFORM_DIRECTIVES} from 'angular2/core';

bootstrap(AppComponent, [
  provide(PLATFORM_DIRECTIVES, {useValue: [BootstrapInputDirective], multi:true})
]);

编辑

是的,您可以创建自己的装饰器来实现这一点.这是一个示例:

Yes, you could create your own decorator to implement this. Here is a sample:

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 {
}

注意我们需要提供父类作为装饰器的输入,因为我们可以在装饰器中找到这个父类.只有这个类的原型和元数据被应用到这个类上,而不是通过反射元数据应用到关联的原型上.

Note that we need to provide the parent class as input of the decorator since we can find out this parent class within the decorator. Only the prototype of this class but the metadata are applied on the class and not on the associated prototype by reflect-metadata.

Edit2

感谢 Nitzam 的回答,这是一个改进:

Thanks to Nitzam's answer, here is an improvment:

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 属性来引用自定义装饰器中的父类.

There is no need for a parent attribute to reference the parent class in the custom decorator.

查看此 plunkr:https://plnkr.co/edit/ks1iK41sIBFlYDb4aTHG?p=preview.

See this plunkr: https://plnkr.co/edit/ks1iK41sIBFlYDb4aTHG?p=preview.

看到这个问题:

这篇关于使用基类装饰器扩展组件装饰器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆