如何扩展/继承组件? [英] How to extend / inherit components?

查看:24
本文介绍了如何扩展/继承组件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为一些已经部署在 Angular 2 中的组件创建扩展,而不必几乎完全重写它们,因为基础组件可能会发生变化,并希望这些变化也反映在其派生组件中.

我创建了这个简单的例子来试图更好地解释我的问题:

使用以下基础组件app/base-panel.component.ts:

import {Component, Input} from 'angular2/core';@成分({选择器:'基本面板',模板:'<div class="panel" [style.background-color]="color" (click)="onClick($event)">{{content}}</div>',样式:[`.控制板{填充:50px;}`]})导出类 BasePanelComponent {@Input() 内容:字符串;颜色:字符串=红色";点击(事件){console.log("点击颜色:" + this.color);}}

您是否想创建另一个衍生组件,例如仅更改示例颜色中的基本组件行为,app/my-panel.component.ts:

import {Component} from 'angular2/core';从 './base-panel.component' 导入 {BasePanelComponent}@成分({选择器:'我的面板',模板:'<div class="panel" [style.background-color]="color" (click)="onClick($event)">{{content}}</div>',样式:[`.控制板{填充:50px;}`]})导出类 MyPanelComponent 扩展了 BasePanelComponent{构造函数(){极好的();this.color = "蓝色";}}

Plunker 中的完整工作示例

<块引用>

注意:显然这个例子很简单,可以解决,否则不需要使用继承,但它只是为了说明真正的问题.

在衍生组件app/my-panel.component.ts的实现中可以看到,大部分实现都重复了,真正继承的部分是 BasePanelComponent,但是 @Component 基本上必须完全重复,而不仅仅是更改的部分,如 selector: 'my-panel'.

是否有某种方法可以从字面上完全继承 Angular2 组件,继承标记/注释的 class 定义,例如 @Component?

编辑 1 - 功能请求

<块引用>

功能请求 angular2 添加到 GitHub 上的项目:扩展/继承 angular2 组件注释 #7968

编辑 2 - 关闭的请求

<块引用>

请求已关闭,出于这个原因,不知道如何合并装饰器.让我们别无选择.所以我的意见是在问题中引用.

解决方案

替代解决方案:

Thierry Templier 的这个答案是解决问题的另一种方法.

在向 Thierry Templier 提出一些问题后,我得出了以下工作示例,它符合我的期望,可以替代此问题中提到的继承限制:

1 - 创建自定义装饰器:

export function CustomComponent(annotation: any) {返回函数(目标:函数){var parentTarget = Object.getPrototypeOf(target.prototype).constructor;var parentAnnotations = Reflect.getMetadata('annotations', parentTarget);var parentAnnotation = parentAnnotations[0];Object.keys(parentAnnotation).forEach(key => {如果(isPresent(parentAnnotation[key])){//验证是注解 typeof 函数if(typeof annotation[key] === 'function'){annotation[key] = annotation[key].call(this, parentAnnotation[key]);}否则如果(//在注释库中强制覆盖!isPresent(注解[key])){注释[key] = parentAnnotation[key];}}});var元数据=新组件(注释);Reflect.defineMetadata('annotations', [元数据], target);}}

2 - 带有@Component 装饰器的基础组件:

@Component({//为测试覆盖属性创建选择器基础选择器:'主人',模板:`<div>测试</div>`})导出类 AbstractComponent {}

3 - 带有 @CustomComponent 装饰器的子组件:

@CustomComponent({//覆盖属性注解//选择器:'子',选择器:(父选择器)=>{ 返回 parentSelector + 'sub'}})导出类 SubComponent 扩展 AbstractComponent {构造函数(){}}

Plunkr 与完整示例.

I would like to create extensions for some components already deployed in Angular 2, without having to rewrite them almost completely, as the base component could undergo changes and wish these changes were also reflected in its derived components.

I created this simple example to try to explain better my questions:

With the following base component 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);
  }
}

Would you like to create another derivative component only alter, for example, a basic component behavior in the case of the example 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

Note: Obviously this example is simple and could be solved otherwise no need to use inheritance, but it is intended only to illustrate the real problem.

As you can see in the implementation of the derivative component app/my-panel.component.ts, much of the implementation was repeated, and the single part really inherited was the class BasePanelComponent, but the @Component had to basically be completely repeated, not just the changed portions, as the selector: 'my-panel'.

Is there some way to make a literally full inheritance of a component Angular2, inheriting the class definition of the markings/annotations, as for example @Component?

Edit 1 - Feature Request

Feature request angular2 added to the project on GitHub: Extend/Inherit angular2 components annotations #7968

Edit 2 - Closed Request

The request was closed, for this reason, that briefly would not know how to merge the decorator will be made. Leaving us with no options. So my opinion is is quoted in the Issue.

解决方案

Alternative Solution:

This answer of Thierry Templier is an alternative way to get around the problem.

After some questions with Thierry Templier, I came to the following working example that meets my expectations as an alternative to inheritance limitation mentioned in this question:

1 - Create custom decorator:

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 - Base Component with @Component decorator:

@Component({
  // create seletor base for test override property
  selector: 'master',
  template: `
    <div>Test</div>
  `
})
export class AbstractComponent {

}

3 - Sub component with @CustomComponent decorator:

@CustomComponent({
  // override property annotation
  //selector: 'sub',
  selector: (parentSelector) => { return parentSelector + 'sub'}
})
export class SubComponent extends AbstractComponent {
  constructor() {
  }
}

Plunkr with complete example.

这篇关于如何扩展/继承组件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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