Angular компонент Наследование и наследование подписок - PullRequest
6 голосов
/ 17 июня 2020

Пусть ниже представлен компонент, который я буду расширять в других компонентах, чтобы повторно использовать какой-то код ..

import { Component } from '@angular/core';

@Component ({
   selector: 'my-app',
   template: ` <div>
      <h1>{{appTitle}}</h1>
      <div>To Tutorials Point</div>
   </div> `,
})

export class AppComponent {
   appTitle: string = 'Welcome';
   ngOnInit(){
      this.registerSomeSubscriptions();
   }
   registerSomeSubscriptions(){
      this.subscribeSomething.subscribe((data)=>{
         performSomeAction();
      })
   }


}

Я могу расширить его, как показано ниже

 import { Component } from '@angular/core';

@Component ({
   selector: 'my-app',
   template: ` <div>
      <h1>{{appTitle}}</h1>
      <div>To Tutorials Point</div>
   </div> `,
})

export class ChildComponent extends AppComponent {
   
}

Хотя я знаю что члены publi c компонента будут доступны в дочернем компоненте.

Мой вопрос

  1. Нужно ли мне по-прежнему использовать отдельные файлы html для обоих компонентов или Это какой-то стиль кода или техника решения проблем для повторного использования одного и того же шаблона html вместе с некоторой дочерней реализацией c с помощью какой-то техники, о которой я не знаю.

Ответы [ 5 ]

2 голосов
/ 24 июня 2020

Дочерние компоненты могут использовать тот же шаблон html, что и родительский компонент, или они могут иметь свои собственные файлы html, в этом случае html родительского компонента не будет использоваться.

Если вы хотите использовать html родительского компонента с некоторыми изменениями в дочерних компонентах, вы можете повторно использовать родительский компонент вместо того, чтобы наследовать его.

  • сделайте родительский компонент повторно используемым компонентом
  • в шаблоне дочернего / функционального компонента, добавьте родительский компонент, используя его селектор
    // add something specific to child/feature component here
    <app-reusable-component></app-reusable-component>
    // add something specific to child/feature component here

html повторно используемого компонента будет доступен вместе с дополнительным html, который вы добавите в компонентах html.

  • для передачи данных между повторно используемым компонентом и компонентом функции используйте взаимодействие компонентов - Input и Output.

  • Input - Передача данных из компонента функции в компонент многократного использования с привязкой ввода

reusable-component.ts:
export class ReusableComponent implements OnInit {
   @Input() dataIn: Observable<object>;
   ngOnInit() {
     dataIn.subscribe(data => {
       // display data
     });
   }
}

feature-component.html:
...
<app-reusable-component [dataIn]="dataToDisplay$"></app-reusable-component>
...

feature-component.ts:
export class FeatureComponent implements OnInit {
  public dataToDisplay$: Observable<object>;
  ngOnInit() {
    this.dataToDisplay$ = this.http.get(url);
  }
}
  • Output - Sen d данные / события из повторно используемого компонента в компонент функции
reusable-component.ts:
export class ReusableComponent implements OnInit {
   @Input() dataIn: Observable<object>;
   @Output() eventOut: EventEmitter<object> = new EventEmitter<object>();
   ngOnInit() {
     dataIn.subscribe(data => {
       // display data
     });
   }
   userInput(value) {
      this.eventOut.emit(value);
   }
}

feature-component.html:
...
<app-reusable-component [dataIn]="dataToDisplay$" (eventOut) ="handleUserData($event)"></app-reusable-component>
...

feature-component.ts:
export class FeatureComponent implements OnInit {
  public dataToDisplay$: Observable<object>;
  ngOnInit() {
    this.dataToDisplay$ = this.http.get(url);
  }
  handleUserData(value) {
    this.http.post(url, value);
  }
}

В этом подходе вы можете повторно использовать шаблон родительского компонента во всех своих дочерних компонентах / компонентах, и вы сможете добавить дополнительные html содержимое в ваших дочерних / функциональных компонентах и ​​передавать данные между ними.

1 голос
/ 24 июня 2020

Если вы просто хотите повторно использовать один и тот же шаблон для дочерних и родительских компонентов, вам просто нужно поместить этот шаблон в файл html и ссылаться на него с помощью templateUrl. Ваши подписки будут унаследованы, и вы сможете получить доступ к publi c защищенным и защищенным переменным из дочернего компонента.

Теперь, если вы хотите унаследовать родительский шаблон, но сможете вносить изменения в шаблон , это немного сложнее, потому что angular не обеспечивает наследования шаблонов.

Возможной альтернативой является использование механизма шаблонов для генерации html. В одном из наших проектов мы использовали nunjucks , чтобы обойти это ограничение.

Итак, по сути, вы указываете html родительского компонента, используя шаблон nunjucks

parent.component. html .njk

<div>

Parent template

{% block specific %}
{% endblock %}

</div>

parent.component.ts

@Component ({
   selector: 'app-parent',
   templateUrl: `parent.component.html`, //Reference compiled template (not .njk)
})
export class ParentComponent
{
    //...
    

И затем вы также определяете свой дочерний компонент как шаблон nunjucks, который наследуется от родительского шаблона

child.component. html .njk

{% extends '/path/to/parent/parent.component.html.njk' %}

{% block specific %}
  Child content: {{childContent}}
{%endblock %}

child.component.ts

@Component ({
   selector: 'app-child',
   templateUrl: `child.component.html`, //reference .html, not .njk
})
export class ChildComponent extends ParentComponent
{
  public childContent = "hello";

  //Access to public/protected members and methods from parent componenent
   
  

Вдобавок к этому у нас есть базовый c сценарий просмотра, который отслеживает изменения файла .njk и генерирует соответствующие html

часы. js

const nunjucks = require('nunjucks');

//Nunjuck config to use <$ and $> for tags, instead of {{ and }}, to avoid conflicting with angular
const nunjucksEnv = nunjucks.configure(
  {
    noCache: true,

    tags:
      {
        variableStart: '<$',
        variableEnd: '$>',
      }
  }
);

//Add watch loop here. Whenever a njk file changes, call the code below
nunjucks.render(njkTemplateFileThatJustChanged, {}, function (err, html)
{
  if (!err)
  {
    let compiledPath = njkTemplateFileThatJustChanged.replace('.njk', '');
    fs.writeFileSync(compiledPath, html);
  }
}
0 голосов
/ 29 июня 2020

https://plnkr.co/edit/HNG0ndIErlOfVnMl?preview

Только что использовали селектор родительского компонента в шаблоне дочернего компонента. Проверьте код, который я добавил в app.ts.

0 голосов
/ 27 июня 2020

Возможно, вы не сможете расширить htmls, но вы можете использовать шаблоны несколькими способами:

  1. Установите TemplateRef базового шаблона в службе, используйте directive, чтобы использовать его позже где угодно.

    A: Недостатком этого является то, что базовый компонент должен быть создан вручную и будет находиться в памяти, пока контейнер не появится в поле зрения. [см. пример - BaseOneComponent]

    B. Если в шаблоне не слишком много привязок, вы можете инициализировать его в самом root (AppComponent).

  2. Создайте общий компонент для заполнителя BaseTwoComponent и используйте <ng-content> для проецирования данных из потребительского компонента [DerivedTwoComponent]. Вы также можете создать несколько заполнителей для <ng-content> и использовать их с селекторами. Ознакомьтесь с Angular Руководством по проецированию контента , чтобы узнать, как использовать несколько слотов для проецирования контента.

Stackblitz: Расширение шаблона

0 голосов
/ 25 июня 2020

, если шаблон находится в файле, вы можете использовать его повторно. @Component - это декоратор, который назначает некоторые «метаданные» для «компонента», чтобы вы не унаследовали их от расширенного класса. Если шаблон находится в отдельном файле, вы можете использовать его в свойстве templateUrl: декоратора @Component.

...