首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何扩展/继承组件?

如何扩展/继承组件?
EN

Stack Overflow用户
提问于 2016-04-07 20:03:21
回答 11查看 175.6K关注 0票数 185

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

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

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

代码语言:javascript
运行
复制
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中的基本组件行为

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

EN

回答 11

Stack Overflow用户

发布于 2016-06-28 21:10:29

替代解决方案:

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

在提了几个问题之后,我得到了下面的工作示例,它满足了我的期望,作为这个问题中提到的继承限制的替代方案:

1-创建自定义装饰器:

代码语言: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])) {
        // 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装饰器的基础组件:

代码语言:javascript
运行
复制
@Component({
  // create seletor base for test override property
  selector: 'master',
  template: `
    <div>Test</div>
  `
})
export class AbstractComponent {

}

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

代码语言:javascript
运行
复制
@CustomComponent({
  // override property annotation
  //selector: 'sub',
  selector: (parentSelector) => { return parentSelector + 'sub'}
})
export class SubComponent extends AbstractComponent {
  constructor() {
  }
}

Plunkr with complete example.

票数 43
EN

Stack Overflow用户

发布于 2016-12-27 22:05:34

Angular 2版本2.3刚刚发布,它包含了本机组件继承。看起来你可以继承和重写任何你想要的东西,除了模板和样式。一些参考资料:

票数 25
EN

Stack Overflow用户

发布于 2019-05-13 17:04:04

让我们了解一下Angular组件继承系统的一些关键限制和特性。

组件只继承类逻辑:

@Component装饰器中的所有元数据都不是inherited.

  • Component @属性,而@
  • 属性是不继承的生命周期。

记住这些特性是非常重要的,所以让我们分别研究它们。

组件只继承类逻辑

当你继承一个组件时,里面的所有逻辑都是同样继承的。值得注意的是,只有公共成员才会被继承,因为私有成员只能在实现它们的类中访问。

@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。

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

https://stackoverflow.com/questions/36475626

复制
相关文章

相似问题

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