Несколько наблюдаемых в родительском компоненте по сравнению с одним наблюдаемым в каждом дочернем компоненте - PullRequest
0 голосов
/ 27 июня 2018

Давайте представим, что у нас есть две модели Player и World, и мы хотим отобразить информацию об игроке с информацией о мире в общем виде. Мы получаем эту информацию через две наблюдаемые playerObservable и worldObvservable. Мы определяем PlayerComponent (родитель), PlayerInformationComponent (ребенок) и WorldInformationComponent (ребенок).

Мне интересно, какое решение является наиболее эффективным:

  • В PlayerComponent я загружаю информацию об игроке и мире параллельно:

    // player.component.ts
    forkJoin([playerObservable, worldObservable])
        .subscribe(([player, world]) => {
            this.player = player;
            this.world = world;
        });
    

    и предоставить каждую информацию соответствующему компоненту:

    // player.component.html
    <app-player [player]="player"></app-player>
    <app-world [world]="world"></app-world>
    

    с ngIf в каждом дочернем компоненте:

    // player-information.component.html
    <div *ngIf="player">...</div>
    
    // world-information.component.html
    <div *ngIf="world">...</div>
    

    И @Input в каждом:

    // player-information.component.ts
    @Input() public player: Player;
    
    // world-information.component.ts
    @Input() public world: World;
    
  • Каждый дочерний компонент загружает свою собственную информацию:

    // player-information.component.ts
    playerObservable.subscribe((player) => { this.player = player; });
    
    // world-information.component.ts
    worldObservable.subscribe((world) => { this.world = world; });
    

    А:

    // player.component.html
    <app-player></app-player>
    <app-world></app-world>
    

Ответы [ 2 ]

0 голосов
/ 28 июня 2018

Используйте services для обмена данными
Angular отличает компоненты от сервисов для повышения модульности и возможности повторного использования. and It's Good Practice to Delegate complex component logic to services

С Angular Style Guide
Ограничивать логику в компоненте только что требуется для просмотра. Вся остальная логика должна быть делегирована услуги.

Переместите многократно используемую логику в сервисы и сделайте компоненты простыми и сосредоточены на их назначении.

Почему? Логика может быть многократно использована несколькими компонентами, если обслуживать и выставлять через функцию.

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

Почему? Удаляет зависимости и скрывает детали реализации из компонент.

Почему? Делает компонент тонким, аккуратным и сфокусированным.

Если ваша цель состоит в многоадресной передаче данных, используйте RXJS Subject или BehaviorSubject Subject действует как мост / прокси между источником Observable и многими observers, позволяя нескольким observers совместно использовать одно и то же Observable исполнение.

Преимущества BehaviorSubject над Subject

  1. Всегда будет возвращать текущее значение при подписке - звонить не нужно onnext().
  2. Имеет функцию getValue() для извлечения последнего значения в виде необработанных данных.
  3. Это гарантирует, что компонент всегда получает самые последние данные.
  4. Вы можете получить наблюдаемое от субъекта поведения, используя asobservable() метод на BehaviorSubject.
  5. Subject vs BehaviorSubject

Услуги

 private firstResponse=new BehaviorSubject<any>('');
     private secondResponse=new BehaviorSubject<any>('');
          CurrentDatafirst = this.firstResponse.asObservable();
          CurrentDatasecond = this.secondResponse.asObservable();
    getdata(){
       forkJoin([playerObservable, worldObservable])
    .subscribe(([player, world]) => {

    this.firstResponse.next(player),
    this.secondResponse.next(world)
  })
    });
   }

Component1:

ngOnInit()
{
  this.service.CurrentDatafirst.subscribe(//value=>your logic);
  this.service.CurrentDatasecond.subscribe(//value=>your logic)

}

Component2:

 ngOnInit()
    {
      this.service.CurrentDatafirst.subscribe(//value=>your logic);
      this.service.CurrentDatasecond.subscribe(//value=>your logic)

    }

RxJS Subjects for human beings

BehaviorSubject in Angular

Live Demo


-------------------------------------------- -----------------------------------------

Вы также можете отправить один запрос http для нескольких наблюдателей с помощью оператора shareReplay и принять соответствующие меры.
Вы должны знать, что http возвращает наблюдаемую холодность и Когда холодный observable имеет кратное subscribers, весь поток данных повторно отправляется для каждого subscriber. Каждый подписчик становится независимым и получает собственный поток данных

Чтобы избежать дублирования HTTP-запросов shareReplay Используется оператор.
Сервис

 public response$:Observable<any>
    getdata(){
               forkJoin([playerObservable, worldObservable]).pipe(sharReplay(1));
            }

   fetchdata()
           {
              this.response$;
            }

Component1:

 ngOnInit()
    {
      this.service.fetchdata().subscribe(//value=>your logic);


    }

Component2:

    ngOnInit()
    {
      this.service.fetchdata().subscribe(//value=>your logic);


    }

Live Demo

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

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

НО

Если у вас много дочерних компонентов, например, вы что-то динамически повторяете через *ngFor, я настоятельно рекомендую получить данные в родительском компоненте и поделиться ими с дочерними. В противном случае у вас будет, например, 50 компонентов и 50 подписок, и это сильно замедлит работу приложения.

...