Jak rozszerzać / dziedziczyć komponenty?

160

Chciałbym stworzyć rozszerzenia dla niektórych komponentów już wdrożonych w Angular 2, bez konieczności ich prawie całkowitego przepisywania, ponieważ komponent podstawowy mógłby podlegać zmianom i chciałbym, aby te zmiany również znalazły odzwierciedlenie w komponentach pochodnych.

Stworzyłem ten prosty przykład, aby lepiej wyjaśnić moje pytania:

Z następującym składnikiem podstawowym 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);
  }
}

Czy chciałbyś stworzyć inny składnik pochodny tylko zmienić np. Podstawowe zachowanie komponentu w przypadku przykładowego koloru 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";
  }
}

Kompletny przykład roboczy w Plunker

Uwaga: Oczywiście ten przykład jest prosty i mógłby zostać rozwiązany w przeciwnym razie nie ma potrzeby używania dziedziczenia, ale ma on jedynie zilustrować rzeczywisty problem.

Jak widać w implementacji składnika pochodnego app/my-panel.component.ts, większość implementacji została powtórzona, a pojedyncza część naprawdę odziedziczyła class BasePanelComponent, ale w @Componentzasadzie musiała zostać całkowicie powtórzona, a nie tylko zmienione części, ponieważ selector: 'my-panel'.

Czy jest jakiś sposób na dosłownie pełne dziedziczenie komponentu Angular2, dziedzicząc na przykład classdefinicję oznaczeń / adnotacji @Component?

Edycja 1 - żądanie funkcji

Żądanie funkcji angular2 dodane do projektu na GitHub: Rozszerz / dziedzicz adnotacje komponentów angular2 # 7968

Edycja 2 - żądanie zamknięte

Prośba została zamknięta, z tego powodu , że na krótko nie wiedziałem, jak scalić dekorator zostanie wykonany. Zostawiając nas bez opcji. Tak więc moja opinia jest cytowana w numerze .

Fernando Leal
źródło
Sprawdź tę odpowiedź stackoverflow.com/questions/36063627/ ... Pozdrawiam
NicolasB
Ok NicolasB. Ale mój problem dotyczy dziedziczenia dekoratora @Component, który nie jest stosowany do metadanych dziedziczenia. = /
Fernando Leal
ludzie, proszę unikać dziedziczenia z angular. np. eksport klasy PlannedFilterComponent rozszerza AbstractFilterComponent implementuje OnInit {jest bardzo zły. Istnieją inne sposoby udostępniania kodu, np. Usługi i mniejsze komponenty. Dziedziczenie nie jest metodą kątową. Jestem w projekcie kątowym, w którym używali dziedziczenia i są rzeczy, które się psują, takie jak eksportowanie komponentów, które dziedziczą po abstrakcyjnych komponentach, brakuje danych wejściowych klasy abstrakcyjnej.
robert king
1
zamiast tego użyj projekcji treści, np. github.com/angular/components/blob/master/src/material/card/ ... nie używaj dziedziczenia
robert king

Odpowiedzi:

39

Alternatywne rozwiązanie:

Ta odpowiedź Thierry'ego Templiera jest alternatywnym sposobem obejścia problemu.

Po kilku pytaniach z Thierrym Templierem doszedłem do następującego przykładu roboczego, który spełnia moje oczekiwania jako alternatywa dla ograniczenia dziedziczenia wspomnianego w tym pytaniu:

1 - Utwórz niestandardowy dekorator:

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 - Komponent podstawowy z dekoratorem @Component:

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

}

3 - Składnik podrzędny z dekoratorem @CustomComponent:

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

Plunkr z pełnym przykładem.

Fernando Leal
źródło
3
Zakładam, że nie będzie to zgodne z kompilatorem szablonów offline.
Günter Zöchbauer
@ GünterZöchbauer, nie mam wiedzy na temat „szablonu kompilatora offline” Angular2. Ale myślę, że może to nie być zgodne i byłaby to opcja alternatywna. Gdzie przydałby się tryb „kompilator szablonów offline” w Angular2? Możesz mi pokazać coś, żeby lepiej to zrozumieć? Dzięki temu mogę zrozumieć znaczenie tej kompatybilności dla mojego projektu.
Fernando Leal
Kompilator szablonów offline (OTC) nie jest jeszcze funkcjonalny, mimo że jest już zawarty w RC.3. OTC przeanalizuje dekoratory i wygeneruje kod na etapie kompilacji, gdy zostanie wygenerowane narzędzie wdrożeniowe. OTC pozwala usunąć parser i kompilator Angular2, który przetwarza dekoratory i powiązania w czasie wykonywania, co prowadzi do zauważalnego mniejszego rozmiaru kodu i szybszej inicjalizacji aplikacji i komponentów. OTC prawdopodobnie stanie się użyteczne w jednej z kolejnych aktualizacji.
Günter Zöchbauer
1
@ GünterZöchbauer, teraz rozumiem znaczenie utrzymania funkcjonalności zgodnej z OTC. Będzie to wstępna kompilacja dekoratorów kątowych, zmniejszająca obciążenie związane z inicjalizacją komponentów. Chciałbym wiedzieć o funkcjonowaniu tego procesu i ponieważ rozwiązanie tej odpowiedzi nie będzie kompatybilne z OTC? Jak wygląda wstępna kompilacja dekoratorów? Mając tę ​​wiedzę, moglibyśmy wymyślić coś, co utrzymałoby tę funkcjonalną alternatywę dla OTC. Dziękuję za wyjaśnienie!
Fernando Leal
24

Angular 2 w wersji 2.3 został właśnie wydany i zawiera natywne dziedziczenie komponentów. Wygląda na to, że możesz dziedziczyć i zastępować, co chcesz, z wyjątkiem szablonów i stylów. Niektóre odniesienia:

Daniel Griscom
źródło
Jedna „gotcha” występuje, gdy zapomnisz określić nowy „selektor” w komponencie potomnym. More than one component matched on this elementJeśli tego nie zrobisz, pojawi się błąd wykonania podobny do tego.
The Aelfinn
@TheAelfinn Tak: każdy komponent musi mieć pełną specyfikację w @Component()tagu. Możesz jednak udostępnić plik .html lub .css, odwołując się do tego samego pliku, jeśli chcesz. W sumie to duży plus.
Daniel Griscom
W twoim drugim linku scotch.io/tutorials/component-inheritance-in-angular-2 , autor twierdzi, że komponenty dziedziczą usługi wstrzyknięte zależności swoich rodziców, mój kod sugeruje inaczej. Czy możesz potwierdzić, że jest to obsługiwane?
The Aelfinn
18

Teraz, gdy TypeScript 2.2 obsługuje mieszanki za pomocą wyrażeń klas , mamy znacznie lepszy sposób wyrażania miksów w składnikach. Pamiętaj, że możesz również użyć dziedziczenia komponentów od wersji angular 2.3 ( dyskusja ) lub niestandardowego dekoratora, jak omówiono w innych odpowiedziach tutaj. Uważam jednak, że Mixiny mają pewne właściwości, które sprawiają, że są preferowane do ponownego wykorzystania zachowania w różnych składnikach:

  • Miksery komponują się bardziej elastycznie, tj. Można mieszać i dopasowywać miksy na istniejących komponentach lub łączyć miksy w celu utworzenia nowych komponentów
  • Skład mieszanki pozostaje łatwy do zrozumienia dzięki oczywistej linearyzacji do hierarchii dziedziczenia klas
  • Możesz łatwiej uniknąć problemów z dekoratorami i adnotacjami, które są plagą dziedziczenia komponentów ( dyskusja )

Zdecydowanie sugeruję przeczytanie powyższego ogłoszenia TypeScript 2.2, aby zrozumieć, jak działają Mixiny. Połączone dyskusje w kątowych problemach GitHub zawierają dodatkowe szczegóły.

Będziesz potrzebować tych typów:

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

export class MixinRoot {
}

Następnie możesz zadeklarować Mixin taki jak ten, Destroyablektóry pomaga komponentom śledzić subskrypcje, które należy usunąć 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
    }
  };
}

Aby wmieszać Destroyablew a Component, deklarujesz swój komponent w ten sposób:

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

Pamiętaj, że MixinRootjest to konieczne tylko wtedy, gdy chcesz extendstworzyć kompozycję Mixin. Możesz łatwo przedłużyć wiele miksów, np A extends B(C(D)). To oczywista linearyzacja miksów, o której mówiłem powyżej, np. Efektywnie tworzysz hierarchię dziedziczenia A -> B -> C -> D.

W innych przypadkach, np. Gdy chcesz skomponować składanki na istniejącej klasie, możesz zastosować składankę w następujący sposób:

const MyClassWithMixin = MyMixin(MyClass);

Jednak okazało się, że pierwszy sposób działa najlepiej w przypadku Componentsi Directives, ponieważ te również muszą być ozdobione @Componentlub @Directivetak czy inaczej.

Johannes Rudolph
źródło
to jest niesamowite! dzieki za sugestie. czy MixinRoot jest tutaj po prostu używany jako pusty symbol zastępczy klasy? chcę się tylko upewnić, że rozumiem poprawnie.
Alex Lockwood
@AlexLockwood tak, pusty symbol zastępczy klasy jest dokładnie tym, do czego go używam. Z radością bym go unikał, ale na razie nie znalazłem lepszego sposobu, aby to zrobić.
Johannes Rudolph
2
Skończyło się na używaniu function Destroyable<T extends Constructor<{}>>(Base = class { } as T). W ten sposób mogę tworzyć miksy za pomocą extends Destroyable().
Alex Lockwood
1
Wygląda to bardzo dobrze, jednak wydaje się, że kompilacja AoT (Cli1.3) usuwa ngOnDestroy z DashBoardComponent, ponieważ nigdy nie jest wywoływany. (to samo dotyczy ngOnInit)
dzolnjan
dzięki za to rozwiązanie. Jednak po zbudowaniu produ za pomocą jonowego lub kątowego CLI, mixin w jakiś sposób nie działa, jakby nie został przedłużony.
Han Che,
16

aktualizacja

Dziedziczenie komponentów jest obsługiwane od wersji 2.3.0-rc.0

oryginalny

Jak dotąd, najbardziej wygodny dla mnie jest, aby zachować szablon i style w odrębny *htmli *.cssplików oraz określenie tych, dzięki templateUrli styleUrlstak łatwo jest wielokrotnego użytku.

@Component {
    selector: 'my-panel',
    templateUrl: 'app/components/panel.html', 
    styleUrls: ['app/components/panel.css']
}
export class MyPanelComponent extends BasePanelComponent
am0wa
źródło
2
Właśnie tego potrzebuję. Jak wyglądałby dekorator @Component dla BasePanelComponent? Czy może odwoływać się do różnych plików html / css? Czy może odwoływać się do tych samych plików html / css, do których odwołuje się MyPanelComponent?
ebhh2001,
1
To nie dziedziczy @Input()i @Output()dekoratorów, prawda?
Leon Adler
10

O ile wiem, dziedziczenie komponentów nie zostało jeszcze zaimplementowane w Angular 2 i nie jestem pewien, czy mają takie plany, jednak skoro Angular 2 używa maszynopisu (jeśli zdecydowałeś się pójść tą drogą), możesz użyć dziedziczenia klas robiąc class MyClass extends OtherClass { ... }. Jeśli chodzi o dziedziczenie komponentów, sugerowałbym zaangażowanie się w projekt Angular 2, przechodząc do https://github.com/angular/angular/issues i wysyłając żądanie funkcji!

Watzon
źródło
Rozumiem, spróbuję w następnych dniach iterować mi projekt angular2 i sprawdzić, czy funkcja żądania nie jest już w problemach projektu w Git, a jeśli nie, sporządzę żądanie zasobu, ponieważ wydaje mi się bardzo interesujące funkcja. Jakieś dodatkowe argumenty, aby złożyć najciekawszą prośbę?
Fernando Leal
1
Jeśli chodzi o maszynopis zasobu dziedziczenia, którego już używam w moim początkowym rozwiązaniu ( export class MyPanelComponent extends BasePanelComponent), problem występuje tylko w przypadku, gdy adnotacje / dekoratory nie są dziedziczone.
Fernando Leal
1
Tak, naprawdę nie wiem, co jeszcze mógłbyś dodać. Podoba mi się pomysł posiadania nowego dekoratora (czegoś podobnego @SubComponent()), który oznacza klasę jako @Componentskładnik podrzędny, lub dodatkowego pola w dekoratorze, które umożliwia odwołanie się do komponentu nadrzędnego w celu dziedziczenia.
Watzon,
1
Prośba o funkcję angular2 dodana do projektu na GitHub: Rozszerz / dziedzicz adnotacje komponentów angular2 # 7968
Fernando Leal
9

Pozwól nam zrozumieć niektóre kluczowe ograniczenia i funkcje systemu dziedziczenia komponentów Angulara.

Komponent dziedziczy tylko logikę klasy:

  • Wszystkie metadane w dekoratorze @Component nie są dziedziczone.
  • Właściwości komponentu @Input i właściwości @Output są dziedziczone.
  • Cykl życia komponentu nie jest dziedziczony.

Należy pamiętać o tych cechach, więc przeanalizujmy każdą z nich niezależnie.

Komponent dziedziczy tylko logikę klasy

Kiedy dziedziczysz komponent, cała logika wewnątrz jest dziedziczona w równym stopniu. Warto zauważyć, że tylko członkowie publiczni są dziedziczeni, ponieważ członkowie prywatni są dostępni tylko w klasie, która je implementuje.

Wszystkie metadane w dekoratorze @Component nie są dziedziczone

Fakt, że żadne metadane nie są dziedziczone, może początkowo wydawać się sprzeczny z intuicją, ale jeśli się nad tym zastanowić, ma to sens. Jeśli dziedziczysz z elementu, powiedzmy (składnikA), nie chcesz, aby selektor składnika ComponentA, z którego dziedziczysz, zastępował selektor składnika ComponentB, który jest klasą dziedziczącą. To samo można powiedzieć o szablonie / templateUrl, jak również o style / styleUrls.

Właściwości komponentu @Input i @Output są dziedziczone

To kolejna funkcja, którą naprawdę uwielbiam w dziedziczeniu komponentów w Angular. W prostym zdaniu, gdy masz niestandardową właściwość @Input i @Output, te właściwości są dziedziczone.

Cykl życia komponentu nie jest dziedziczony

Ta część nie jest tak oczywista, zwłaszcza dla osób, które nie pracowały intensywnie z zasadami OOP. Na przykład załóżmy, że masz ComponentA, który implementuje jeden z wielu haków cyklu życia Angulara, takich jak OnInit. Jeśli utworzysz ComponentB i odziedziczysz ComponentA, cykl życia OnInit z ComponentA nie zostanie uruchomiony, dopóki nie zostanie jawnie wywołany, nawet jeśli masz ten cykl życia OnInit dla ComponentB.

Wywołanie metod komponentów Super / Base

Aby uzyskać metodę ngOnInit () z programu ComponentA fire, musimy użyć słowa kluczowego super, a następnie wywołać potrzebną metodę, którą w tym przypadku jest ngOnInit. Słowo kluczowe super odnosi się do instancji dziedziczonego komponentu, z którego w tym przypadku będzie ComponentA.

Masoud Bimar
źródło
5

jeśli czytasz biblioteki CDK i biblioteki materiałów, używają one dziedziczenia, ale nie tak bardzo dla samych komponentów, projekcja zawartości jest królem IMO. zobacz ten link https://blog.angular-university.io/angular-ng-content/ gdzie jest napisane „kluczowy problem z tym projektem”

Wiem, że to nie odpowiada na twoje pytanie, ale naprawdę uważam, że należy unikać dziedziczenia / rozszerzania składników . Oto moje rozumowanie:

Jeśli klasa abstrakcyjna rozszerzona o dwa lub więcej komponentów zawiera logikę współdzieloną: użyj usługi lub nawet utwórz nową klasę maszynopisu, która może być współużytkowana między dwoma komponentami.

Jeśli klasa abstrakcyjna ... zawiera zmienne wspólne lub funkcje onClicketc, nastąpi duplikacja między kodem HTML dwóch rozszerzających się widoków komponentów. To jest zła praktyka i że współdzielony kod HTML musi zostać podzielony na komponenty. Te komponenty (części) mogą być współużytkowane przez te dwa komponenty.

Czy brakuje mi innych powodów, dla których warto mieć abstrakcyjną klasę komponentów?

Przykładem, który ostatnio widziałem, były komponenty rozszerzające funkcję AutoUnsubscribe:

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

był to bas, ponieważ w dużej bazie kodu infiniteSubscriptions.push()był używany tylko 10 razy. Również importowanie i rozszerzenie AutoUnsubscribefaktycznie zajmuje więcej niż tylko dodanie kodu mySubscription.unsubscribe()w ngOnDestroy()metodzie samego komponentu, który wymagał dodatkowej logiki i tak.

Robert King
źródło
Ok, rozumiem twoją kolokację i zgadzam się, że agregacja prawie rozwiązuje wszystkie problemy, które wydają się wymagać dziedziczenia. Zawsze warto myśleć o komponentach jako o małych częściach aplikacji, które można zadokować na różne sposoby. Ale w przypadku pytania problem polega na tym, że nie mam kontroli / dostępu do modyfikacji w komponencie, który chcę odziedziczyć (jest to komponent trzeci), wtedy agregacja stałaby się niewykonalna, a dziedziczenie byłoby idealnym rozwiązaniem.
Fernando Leal
dlaczego nie możesz po prostu stworzyć nowego komponentu, który zawiera ten komponent innej firmy? Jaki jest twój komponent innej firmy poza interesem? np. <my-calendar [stuff] = stuff> <third-party-calendar [stuff] = stuff> </ ..> </ ..>
robert king
@robertking powtarzanie siebie to bardzo słaby schemat ... Dlatego zaczniesz nienawidzić swojej pracy ... zamiast czerpać z niej przyjemność.
Dariusz Filipiak
Jeśli chodzi o mnie, dobrym pomysłem jest rozszerzenie komponentów na wypadek, gdybyś chciał mieć te same parametry wejścia / wyjścia dla zestawu komponentów, aby mogły zachowywać się jak jeden. Na przykład mam kilka kroków rejestracji (credentialsStep, addressStep, selectBenefitsStep). Wszystkie powinny mieć te same opcje wejścia (stepName, actionButtons ...) i wyjścia (zakończ, anuluj).
Sergey_T,
@Sergey_T czy mógłbyś rozważyć jeden komponent z wyborem ng i projekcją treści? Również powtórzenie kilku danych wejściowych nie wydaje się, abyś naprawdę oszczędzał na dużej funkcjonalności TBH.
robert king
2

Jeśli ktoś szuka zaktualizowanego rozwiązania, odpowiedź Fernando jest prawie idealna. Z wyjątkiem tego, że ComponentMetadatazostało wycofane. Za pomocąComponent zamiast tego zadziałało dla mnie.

Pełny CustomDecorator.tsplik dekoratora niestandardowego wygląda następująco:

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

Następnie zaimportuj go do nowego sub-component.component.tspliku komponentu i użyj @CustomComponentzamiast @Componenttego:

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

...

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

  constructor() {
    super();
  }

  // Add new logic here!
}
rhyneav
źródło
Czy dekoratorzy na zamówienie nie są zbyt odradzani? Z wielu innych postów / wątków to rozwiązanie zostało oznaczone jako całkowicie błędne, ponieważ AOT ich nie obsługuje?
TerNovi
2

Możesz dziedziczyć @Input, @Output, @ViewChild itp. Spójrz na przykład:

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

}
Mizuwokiru
źródło
1

Komponenty można rozszerzać tak samo, jak dziedziczenie klas maszynopisu, tyle że trzeba nadpisać selektor nową nazwą. Wszystkie właściwości Input () i Output () z komponentu nadrzędnego działają normalnie

Aktualizacja

@Component jest dekoratorem,

Dekoratory są stosowane podczas deklaracji klasy, a nie na obiektach.

Zasadniczo dekoratory dodają pewne metadane do obiektu klasy i nie można uzyskać do nich dostępu przez dziedziczenie.

Jeśli chcesz uzyskać dziedziczenie dekoratora, zasugerowałbym napisanie niestandardowego dekoratora. Coś jak poniżej przykład.

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

Zobacz: https://medium.com/@ttemplier/angular2-decorators-and-class-inheritance-905921dbd1b7

MAHESH VALIYA VEETIL
źródło
Czy mógłbyś zilustrować (na przykładzie pytania), jak by to działało? Możesz użyć stackblitz, aby rozwinąć przykład i udostępnić link.
Fernando Leal
@Component jest dekoratorem, dekoratory są stosowane podczas deklaracji klasy, a nie na obiektach.
MAHESH VALIYA VEETIL
Masz rację. Dekoratory nie robią żadnej różnicy. Jest wymagany tylko wtedy, gdy komponent podstawowy jest używany jako komponent gdzie indziej
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);
        }
}
mittal bhatt
źródło