首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用基类装饰器扩展组件装饰器

用基类装饰器扩展组件装饰器
EN

Stack Overflow用户
提问于 2016-04-25 10:01:48
回答 6查看 27.7K关注 0票数 25

我在每个组件上重复了几个组件装饰声明,例如:

代码语言:javascript
复制
@Component({
    moduleId: module.id,
    directives: [BootstrapInputDirective]
})

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

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2016-04-25 10:04:45

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

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

以下是一个示例:

代码语言:javascript
复制
(...)
import {PLATFORM_DIRECTIVES} from 'angular2/core';

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

编辑

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

代码语言:javascript
复制
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装饰器:

代码语言:javascript
复制
@Component({
  template: `
    <div>Test</div>
  `
})
export class AbstractComponent {
}

@CustomComponent({
  selector: 'sub',
  parent: AbstractComponent
})
export class SubComponent extends AbstractComponent {
}

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

Edit2

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

代码语言:javascript
复制
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

见这个问题:

票数 28
EN

Stack Overflow用户

发布于 2017-04-27 18:31:48

以防万一您正在寻找isPresent函数:

function isPresent(obj: any): boolean { return obj !== undefined && obj !== null; }

票数 9
EN

Stack Overflow用户

发布于 2016-12-29 12:37:22

在最新版本的角,ComponentMetadata类是不可用的,正如少数成员在这里指出的。

这就是我如何实现CustomComponent使其工作的方式:

代码语言:javascript
复制
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];
      });
  };
}

希望能帮上忙!

编辑:前面的代码块,即使它工作,它覆盖扩展类的原始元数据。在下面找到它的增强版本,允许您在不修改基类的情况下拥有多个继承和重写。

代码语言:javascript
复制
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];
    });
};

}

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36837421

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档