Bileşenler nasıl genişletilir / devralınır?


160

Temel bileşen değişikliklere uğrayabileceğinden ve bu değişikliklerin de türetilmiş bileşenlerine yansıtılmasını dilediğinden, Angular 2'de zaten dağıtılmış bazı bileşenler için uzantıları neredeyse tamamen yeniden yazmak zorunda kalmadan oluşturmak istiyorum.

Sorularımı daha iyi açıklamaya çalışmak için bu basit örneği oluşturdum:

Aşağıdaki temel bileşenle 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);
  }
}

Yalnızca başka bir türev bileşen oluşturmak ister misiniz, örneğin, örnek renk durumunda temel bileşen davranışını değiştirmek ister misiniz 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";
  }
}

Plunker'da eksiksiz çalışma örneği

Not: Açıkçası bu örnek basittir ve aksi halde miras kullanılmasına gerek yoktur, ancak yalnızca gerçek sorunu göstermek amaçlanmıştır.

Türev bileşeninin uygulanmasında görebileceğiniz gibi app/my-panel.component.ts, uygulamanın çoğu tekrarlandı ve gerçekten miras alınan tek parça class BasePanelComponent, ancak, @Componentyalnızca değiştirilen bölümleri değil, tamamen tekrarlanması gerekiyordu selector: 'my-panel'.

classÖrneğin, işaretlerin / ek açıklamaların tanımını devralarak Angular2 bileşeninin tam anlamıyla kalıtımını almanın bir yolu var mı @Component?

Düzenleme 1 - Özellik İsteği

GitHub'daki projeye angular2 özellik isteği eklendi: angular2 bileşenleri ek açıklamalarını genişlet / devral

Düzenle 2 - Kapalı İstek

Bu nedenle , dekoratörün nasıl birleştirileceğini kısaca bilmeyen istek kapatıldı . Bizi seçeneksiz bırakmak. Bu yüzden benim düşüncem Sayıda aktarılıyor .


Bu yanıtı kontrol edin stackoverflow.com/questions/36063627/… Saygılarımızla
NicolasB

Tamam NicolasB. Ancak benim sorunum, miras meta verilerine uygulanmayan dekoratör @Component'in mirasıyla ilgili. = /
Fernando Leal

insanlar, açısal ile kalıtım kullanmaktan kaçının lütfen. örn. export class PlannedFilterComponent genişletiyor AbstractFilterComponent uygular OnInit {çok kötü. Kodu paylaşmanın başka yolları da vardır, örneğin hizmetler ve daha küçük bileşenler. Kalıtım açısal yol değildir. Kalıtım kullandıkları açısal bir projedeyim ve soyut bileşenlerden miras kalan bileşenleri ihraç etmek gibi soyut sınıfın girdilerini eksik olan şeyler var.
robert king

1
bunun yerine içerik projeksiyonu kullanın örn. github.com/angular/components/blob/master/src/material/card/… miras kullanma
Robert

Yanıtlar:


39

Alternatif çözüm:

Thierry Templier'ın bu cevabı problemi çözmenin alternatif bir yoludur.

Thierry Templier ile ilgili bazı sorulardan sonra, bu soruda bahsedilen miras sınırlamasına alternatif olarak beklentilerimi karşılayan aşağıdaki çalışma örneğine geldim:

1 - Özel dekoratör oluşturun:

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 - @ Bileşen dekoratörlü Temel Bileşen:

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

}

3 - @CustomComponent dekoratörlü alt bileşen:

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

Tam örnekle Plunkr.


3
Bunun çevrimdışı şablon derleyici ile uyumlu olmayacağını varsayıyorum.
Günter Zöchbauer

@ GünterZöchbauer, Angular2'nin "offline derleyici şablonu" hakkında hiçbir bilgim yok. Ancak bunun uyumlu olmayabileceğini düşünüyorum ve alternatif bir seçenek olurdu. Angular2'nin "çevrimdışı şablon derleyicisi" modu nerede yararlı olur? Bana bu konuda daha iyi bir şeyler anlatabilir misin? Böylece bu uyumluluğun projem için önemini anlayabiliyorum.
Fernando Leal

Çevrimdışı şablon derleyici (OTC), RC.3'te zaten bulunmasına rağmen henüz işlevsel değildir. OTC, konuşlandırıcılar analiz eder ve konuşlandırılabilir oluşturulduğunda bir oluşturma adımı sırasında kod oluşturur. OTC, dekoratörleri ve bağlamaları çalışma zamanında işleyen Angular2 ayrıştırıcıyı ve derleyiciyi kaldırmaya izin verir, bu da daha küçük kod boyutuna ve daha hızlı uygulama ve bileşen başlatmaya yol açar. OTC muhtemelen bir sonraki güncellemelerden biri ile kullanılabilir hale gelecektir.
Günter Zöchbauer

1
@ GünterZöchbauer, şimdi OTC ile uyumlu işlevselliği korumanın önemini anlıyorum. Bileşenleri başlatmak için ek yükü azaltan açısal dekoratörlerin bir ön derlemesi olacaktır. Bu sürecin işleyişi hakkında bilgi sahibi olmak istiyorum ve bu cevabın çözümü OTC ile uyumlu olmayacağı için mi? Dekoratörlerin ön derlemesi nasıl? Bu bilgiye sahip olarak, OTC'ye bu işlevsel alternatifi koruyacak bir şey düşünebiliriz. Açıklama için teşekkürler!
Fernando Leal

24

Açısal 2 sürüm 2.3 henüz piyasaya sürüldü ve yerel bileşen mirasını içeriyor. Şablonlar ve stiller dışında istediğiniz her şeyi devralabilir ve geçersiz kılabilirsiniz. Bazı referanslar:


Alt bileşende yeni bir "seçici" belirtmeyi unuttuğunuzda burada bir "gotcha" oluşur. Eğer More than one component matched on this elementyoksa satırları boyunca bir çalışma zamanı hatası alırsınız .
Aelfinn

@TheAelfinn Evet: her bileşenin @Component()etikette tam bir spesifikasyon olması gerekir . Ancak, isterseniz aynı dosyaya başvurarak .html veya .css dosyasını paylaşabilirsiniz. Sonuçta, büyük bir artı.
Daniel Griscom

İkinci bağlantınızda scotch.io/tutorials/component-inheritance-in-angular-2 , bileşenlerin ebeveynlerinin bağımlılık enjekte edilen hizmetlerini miras aldığını iddia ediyor, kodum aksini gösteriyor. Bunun desteklendiğini onaylayabilir misiniz?
Aelfinn

18

TypeScript 2.2 artık Mixins ile Class ifadelerini desteklediğine göre , Mixins'i Bileşenler üzerinde ifade etmenin çok daha iyi bir yoluna sahibiz. Ayrıca , burada diğer yanıtlarda tartışıldığı gibi açısal 2.3'ten ( tartışma ) veya özel bir dekoratörden Bileşen mirasını da kullanabileceğinizi unutmayın . Ancak, ben Mixins bileşenleri arasında davranışı yeniden kullanmak için tercih edilen bazı özelliklere sahip olduğunu düşünüyorum:

  • Mixinler daha esnek bir şekilde oluşturulur, yani Mixins'i mevcut bileşenlerle karıştırabilir ve eşleştirebilir veya Mixins'i yeni Bileşenler oluşturmak için birleştirebilirsiniz
  • Bir sınıf miras hiyerarşisine belirgin doğrusallaştırması sayesinde mixin kompozisyonunun anlaşılması kolaydır
  • Bileşen mirasını rahatsız eden dekoratörler ve ek açıklamalarla ilgili sorunları daha kolay önleyebilirsiniz ( tartışma )

Mixins'in nasıl çalıştığını anlamak için yukarıdaki TypeScript 2.2 duyurusunu okumanızı şiddetle tavsiye ederim. Açısal GitHub konularındaki bağlantılı tartışmalar ek ayrıntılar sağlar.

Bu türlere ihtiyacınız olacak:

export type Constructor<T> = new (...args: any[]) => T;

export class MixinRoot {
}

Ve sonra, Destroyablebileşenlerin atılması gereken abonelikleri takip etmesine yardımcı olan bu mixin gibi bir Mixin bildirebilirsiniz ngOnDestroy:

export function Destroyable<T extends Constructor<{}>>(Base: T) {
  return class Mixin extends Base implements OnDestroy {
    private readonly subscriptions: Subscription[] = [];

    protected registerSubscription(sub: Subscription) {
      this.subscriptions.push(sub);
    }

    public ngOnDestroy() {
      this.subscriptions.forEach(x => x.unsubscribe());
      this.subscriptions.length = 0; // release memory
    }
  };
}

A'ya Destroyablekarıştırmak Componentiçin bileşeninizi şu şekilde beyan edersiniz:

export class DashboardComponent extends Destroyable(MixinRoot) 
    implements OnInit, OnDestroy { ... }

Bunun MixinRootyalnızca extendbir Mixin kompozisyonu istediğinizde gerekli olduğunu unutmayın . Birden fazla karışımı kolayca genişletebilirsiniz A extends B(C(D)). Bu, yukarıda bahsettiğim karışımların bariz doğrusallaştırılmasıdır, örneğin etkili bir miras hiyerarşisi oluşturuyorsunuz A -> B -> C -> D.

Diğer durumlarda, örneğin mevcut bir sınıfta Mixins oluşturmak istediğinizde, Mixin'i şu şekilde uygulayabilirsiniz:

const MyClassWithMixin = MyMixin(MyClass);

Ancak, ilk yolun en iyi şekilde çalıştığını buldum Componentsve Directivesbunların da dekore edilmesi @Componentya da @Directiveyine de dekore edilmesi gerekiyor .


bu harika! Önerin için teşekkürler. MixinRoot burada boş bir sınıf yer tutucusu olarak mı kullanılıyor? sadece anlayışımın doğru olduğundan emin olmak istiyorum.
Alex Lockwood

@AlexLockwood evet, boş sınıf yer tutucu tam olarak ne için kullanıyorum. Mutlu bir şekilde kullanmaktan kaçınırdım ama şimdilik bunu yapmak için daha iyi bir yol bulamadım.
Johannes Rudolph

2
Sonunda kullandım function Destroyable<T extends Constructor<{}>>(Base = class { } as T). Bu şekilde kullanarak mixins oluşturabilirim extends Destroyable().
Alex Lockwood

1
Bu çok iyi görünüyor, ancak AoT derlemesi (Cli1.3) ngOnDestroy'u DashBoardComponent'ten asla çağrılmadığı için kaldırıyor gibi görünüyor. (ngOnInit için de aynı şey geçerli)
dzolnjan

bu çözüm için teşekkürler. Bununla birlikte, iyonik veya açısal-klipsli bir ürün yapısından sonra, karışım bir şekilde uzatılmamış gibi çalışmaz.
Han Che

16

Güncelleme

Bileşen devralma 2.3.0-rc.0'dan beri desteklenmektedir

orijinal

Şimdiye kadar, benim için en uygun ayrı içine şablonu & stilleri tutmaktır *html& *.cssdosya ve yoluyla bu belirtmek templateUrlve styleUrlskolay yeniden kullanılabilir yani.

@Component {
    selector: 'my-panel',
    templateUrl: 'app/components/panel.html', 
    styleUrls: ['app/components/panel.css']
}
export class MyPanelComponent extends BasePanelComponent

2
Tam da ihtiyacım olan şey bu. BasePanelComponent için @Component dekoratörü nasıl görünürdü? Farklı html / css dosyalarına başvurabilir mi? MyPanelComponent tarafından başvurulan aynı html / css dosyalarına başvurabilir mi?
ebhh2001

1
Bu miras @Input()ve @Output()dekoratörler değil , değil mi?
Leon Adler

10

Bildiğim kadarıyla, bileşen mirasının henüz Açısal 2'de uygulanmadığını ve planlarının olup olmadığından emin değilim, ancak Açısal 2 dakikayı kullandığından (bu rotayı kullanmaya karar verdiyseniz) sınıf mirasını kullanabilirsiniz yaparak class MyClass extends OtherClass { ... }. Bileşen mirası için, https://github.com/angular/angular/issues adresine gidip bir özellik isteği göndererek Açısal 2 projesine katılmanızı öneririm !


Anladım, önümüzdeki günlerde bana açısal2 projesini yineleyeceğim ve istek özelliğinin Git'teki proje sorunlarında olmadığını doğrulayacağım ve eğer değilse, bana çok ilginç göründüğü için kaynak için bir istek hazırlayacağım özellik. En ilginç talepte bulunmak için ekstra argüman fikri var mı?
Fernando Leal

1
Zaten ilk çözümümde ( export class MyPanelComponent extends BasePanelComponent) kullandığım miras kaynağının yazımıyla ilgili olarak, sorun yalnızca Ek Açıklamalar / Dekoratörler devralınmamışsa söz konusudur.
Fernando Leal

1
Evet, başka ne ekleyebileceğinizi gerçekten bilmiyorum. Ben ya @SubComponent()bir alt bileşen olarak bir sınıf işaretler yeni bir dekoratör (bir şey gibi ) ya da @Componentdekoratör devralmak için bir üst bileşen başvuru sağlayan ekstra bir alana sahip olması fikrini seviyorum .
watzon

1
Özellik talebi angular2 GitHub projesine eklendi: Angular2 bileşenleri ek açıklamalarını genişlet / devral # 7968
Fernando Leal

9

Angular'ın bileşen miras sistemindeki bazı temel sınırlamaları ve özellikleri anlayalım.

Bileşen yalnızca sınıf mantığını devralır:

  • @Component dekoratördeki tüm meta veriler devralınmaz.
  • @Input özellikleri ve @Output özellikleri devralınır.
  • Bileşen yaşam döngüsü miras alınmaz.

Bu özelliklerin akılda tutulması çok önemlidir, bu yüzden her birini bağımsız olarak inceleyelim.

Bileşen yalnızca sınıf mantığını devralır

Bir Bileşeni devraldığınızda, içerideki tüm mantık eşit olarak devralınır. Özel üyeler sadece onları uygulayan sınıfta erişilebilir olduğundan, sadece kamu üyelerinin miras alındığını belirtmek gerekir.

@Component dekoratördeki tüm meta veriler miras alınmaz

Hiçbir meta verinin miras alınmaması ilk başta karşı sezgisel görünebilir, ancak bunu düşünürseniz gerçekten mantıklıdır. Bir Component sayından (componentA) miras alırsanız, miras aldığınız ComponentA seçicisinin, miras alınan sınıf olan ComponentB seçicisini değiştirmesini istemezsiniz. Aynısı şablon / templateUrl ve ayrıca style / styleUrls için de söylenebilir.

@Input ve @Output bileşenleri devralınır

Bu, açısal olarak bileşen kalıtım hakkında gerçekten sevdiğim bir başka özellik. Basit bir cümleyle, özel bir @Input ve @Output özelliğine sahip olduğunuzda, bu özellikler devralınır.

Bileşen yaşam döngüsü miras alınmadı

Bu kısım, özellikle OOP ilkeleri ile kapsamlı bir şekilde çalışmayan insanlar için çok açık olmayan kısımdır. Örneğin, Angular'ın OnInit gibi birçok yaşam döngüsü kancasından birini uygulayan Bileşen A'ya sahip olduğunuzu varsayalım. ComponentB oluşturursanız ve ComponentA'yı devralırsanız, ComponentB için OnInit yaşam döngüsü, ComponentB için bu OnInit yaşam döngüsüne sahip olsanız bile, açıkça çağrılıncaya kadar tetiklenmez.

Süper / Temel Bileşen Yöntemlerini Çağırma

ComponentA ateşinden ngOnInit () yöntemini elde etmek için, super anahtar sözcüğünü kullanmamız ve ardından bu durumda ngOnInit olan ihtiyacımız olan yöntemi çağırmamız gerekir. Super anahtar sözcüğü, devralınmakta olan bileşenin bu durumda ComponentA olacağı örneğini ifade eder.


5

CDK kütüphanelerini ve materyal kütüphanelerini okursanız, kalıtım kullanıyorlar, ancak bileşenlerin kendisi için çok fazla değiller, içerik projeksiyonu kral IMO. bu bağlantıya bakın https://blog.angular-university.io/angular-ng-content/ "bu tasarımla ilgili temel sorun"

Bunun sorunuza cevap vermediğini biliyorum, ancak bileşenlerin miras alınması / genişletilmesinden kaçınılması gerektiğini düşünüyorum . İşte benim akıl yürütmem:

İki veya daha fazla bileşen tarafından genişletilen soyut sınıf, paylaşılan mantık içeriyorsa: bir hizmet kullanın ya da iki bileşen arasında paylaşılabilecek yeni bir tip yazımı sınıfı oluşturun.

Soyut sınıf ... paylaşılan değişkenler veya onClicketc işlevleri içeriyorsa, iki genişletme bileşeni görünümünün html'si arasında çoğaltma olacaktır. Bu kötü bir uygulamadır ve paylaşılan html'nin Bileşen (ler) e bölünmesi gerekir. Bu Bileşenler (parçalar) iki bileşen arasında paylaşılabilir.

Bileşenler için soyut bir sınıfa sahip olmanın başka nedenlerini mi kaçırıyorum?

Son zamanlarda gördüğüm bir örnek AutoUnsubscribe'ı genişleten bileşenlerdi:

import { Subscription } from 'rxjs';
import { OnDestroy } from '@angular/core';
export abstract class AutoUnsubscribeComponent implements OnDestroy {
  protected infiniteSubscriptions: Array<Subscription>;

  constructor() {
    this.infiniteSubscriptions = [];
  }

  ngOnDestroy() {
    this.infiniteSubscriptions.forEach((subscription) => {
      subscription.unsubscribe();
    });
  }
}

çünkü bu büyük bir kod temeli boyunca infiniteSubscriptions.push()sadece 10 kez kullanıldı. Ayrıca ithal & uzanan AutoUnsubscribeaslında sadece eklemekten daha fazla kod alır mySubscription.unsubscribe()içinde ngOnDestroy()zaten ek mantık gerekli bileşeni kendisi yöntemi.


Tamam, kollokasyonunuzu anlıyorum ve toplamanın neredeyse mirasa ihtiyaç duyan tüm sorunları çözdüğüne katılıyorum. Bileşenleri uygulamanın çeşitli şekillerde yerleştirilebilecek küçük parçaları olarak düşünmek her zaman ilginçtir. Ancak soru söz konusu olduğunda, miras almak istediğim bileşendeki (üçüncü bir bileşendir) değişiklik / değişikliklere kontrol / erişime sahip olmamam, daha sonra toplama mümkün olmaz ve kalıtım ideal çözüm olacaktır.
Fernando Leal

neden bu üçüncü taraf bileşenini kapsayan yeni bir bileşen oluşturamıyorsunuz? Üçüncü taraf bileşeninizin ilgisi nedir? örneğin <takvimim [şeyler] = şeyler> <üçüncü taraf takvim [şeyler] = şeyler> </ ..> </ ..>
robert king

@robertking kendini tekrarlamak çok zayıf bir kalıp ... Bu yüzden işinden nefret etmek yerine işinden nefret etmeye başlayacaksın.
Dariusz Filipiak

Bana gelince, bir bileşen seti için aynı Giriş / Çıkış parametrelerine sahip olmak istemeniz durumunda bileşenleri genişletmek iyi bir fikirdir, böylece bunlar bir takım gibi davranabilirler. Örneğin birkaç kayıt adımım var (credentialsStep, addressStep, selectBenefitsStep). Hepsi aynı Giriş seçeneklerine (stepName, actionButtons ...) ve Çıktılara (tam, iptal) sahip olmalıdır.
Sergey_T

@Sergey_T ng seçme ve içerik yansıtma özellikli bir bileşeni düşünebilir misiniz? Ayrıca birkaç girişi tekrarlamak, çok fazla işlevsellik TBH'sinden tasarruf ettiğiniz gibi görünmüyor.
robert king

2

Birisi güncellenmiş bir çözüm arıyorsa, Fernando'nun cevabı neredeyse mükemmeldir. Bunun dışında ComponentMetadatakullanımdan kaldırıldı. ComponentBunun yerine kullanmak benim için çalıştı.

Tam Özel Dekoratör CustomDecorator.tsdosyası şöyle görünür:

import 'zone.js';
import 'reflect-metadata';
import { Component } from '@angular/core';
import { isPresent } from "@angular/platform-browser/src/facade/lang";

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);
  }
}

Ardından yeni bileşen sub-component.component.tsdosyanıza içe aktarın ve @CustomComponentbunun yerine şunu kullanın @Component:

import { CustomComponent } from './CustomDecorator';
import { AbstractComponent } from 'path/to/file';

...

@CustomComponent({
  selector: 'subcomponent'
})
export class SubComponent extends AbstractComponent {

  constructor() {
    super();
  }

  // Add new logic here!
}

Özel dekoratörler son derece cesaret kırılmaz mı? Diğer pek çok gönderi / ileti dizisinden bu çözüm tamamen yanlış olarak işaretlendi çünkü AOT bunları desteklemiyor mu?
TerNovi

2

@Input, @Output, @ViewChild, vb. Miras alabilirsiniz. Örneğe bakın:

@Component({
    template: ''
})
export class BaseComponent {
    @Input() someInput: any = 'something';

    @Output() someOutput: EventEmitter<void> = new EventEmitter<void>();

}

@Component({
    selector: 'app-derived',
    template: '<div (click)="someOutput.emit()">{{someInput}}</div>',
    providers: [
        { provide: BaseComponent, useExisting: DerivedComponent }
    ]
})
export class DerivedComponent {

}

1

Bileşenler, yalnızca seçiciyi yeni bir adla geçersiz kılmak zorunda olduğunuz, bir typecript sınıfı mirası ile aynı şekilde genişletilebilir. Üst Bileşendeki Tüm Giriş () ve Çıkış () Özellikleri normal şekilde çalışır

Güncelleme

@Component bir dekoratördür,

Dekoratörler, nesneler üzerinde değil, sınıf bildirimi sırasında uygulanır.

Temel olarak, dekoratörler sınıf nesnesine bazı meta veriler ekler ve bu bilgilere miras yoluyla erişilemez.

Dekoratör Mirasını elde etmek istiyorsanız özel bir dekoratör yazmanızı öneririm. Aşağıdaki örnek gibi bir şey.

export function CustomComponent(annotation: any) {
    return function (target: Function) {
    var parentTarget = Object.getPrototypeOf(target.prototype).constructor;

    var parentAnnotations = Reflect.getMetadata('annotations', parentTarget);
    var parentParamTypes = Reflect.getMetadata('design:paramtypes', parentTarget);
    var parentPropMetadata = Reflect.getMetadata('propMetadata', parentTarget);
    var parentParameters = Reflect.getMetadata('parameters', parentTarget);

    var parentAnnotation = parentAnnotations[0];

    Object.keys(parentAnnotation).forEach(key => {
    if (isPresent(parentAnnotation[key])) {
        if (!isPresent(annotation[key])) {
        annotation[key] = parentAnnotation[key];
        }
    }
    });
    // Same for the other metadata
    var metadata = new ComponentMetadata(annotation);

    Reflect.defineMetadata('annotations', [ metadata ], target);
    };
};

Bakınız: https://medium.com/@ttemplier/angular2-decorators-and-class-inheritance-905921dbd1b7


Örnek olarak (soru örneğini kullanarak) bu nasıl çalışır? Örneği geliştirmek ve bağlantıyı paylaşmak için stackblitz'i kullanabilirsiniz .
Fernando Leal

@Bileşen bir dekoratördür, Dekoratörler, nesneler üzerinde değil, sınıf bildirimi sırasında uygulanır.
MAHESH VALIYA VEETIL

Haklısın. Dekoratörler hiç fark etmez. Sadece temel bileşen başka bir yerde bileşen olarak kullanılıyorsa gereklidir
MAHESH VALIYA VEETIL

0
just use inheritance,Extend parent class in child class and declare constructor with parent class parameter and this parameter use in super().

1.parent class
@Component({
    selector: 'teams-players-box',
    templateUrl: '/maxweb/app/app/teams-players-box.component.html'
})
export class TeamsPlayersBoxComponent {
    public _userProfile:UserProfile;
    public _user_img:any;
    public _box_class:string="about-team teams-blockbox";
    public fullname:string;
    public _index:any;
    public _isView:string;
    indexnumber:number;
    constructor(
        public _userProfilesSvc: UserProfiles,
        public _router:Router,
    ){}
2.child class
@Component({

    selector: '[teams-players-eligibility]',
    templateUrl: '/maxweb/app/app/teams-players-eligibility.component.html'
})
export class TeamsPlayersEligibilityComponent extends TeamsPlayersBoxComponent{

    constructor (public _userProfilesSvc: UserProfiles,
            public _router:Router) {
            super(_userProfilesSvc,_router);
        }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.