Как разделить свойство числа между двумя компонентами в angular без связи (только через службу)? - PullRequest
0 голосов
/ 14 апреля 2020

Мне нужно поделиться свойством, которое является числом между двумя компонентами, которые не связаны между собой дочерним / родительским элементом. Мне нужен настоящий пример того, как это сделать. На данный момент свойство находится только в одном компоненте, поэтому мне также нужно знать, как передавать данные между ними. Я не буду использовать такие вещи, как щелчок, я хочу знать, могу ли я отправить изменение, когда функция изменяет значение;

, например:

компонент A имеет число (monthValue) - компонент A имеет функцию

setMonthValue(){
    this.monthValue = x;
}

Как оба компонента (A e B) могут иметь это значение? Мне нужно получить / прочитать это значение в B;

Ответы [ 2 ]

1 голос
/ 14 апреля 2020

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

Компонент не должен иметь «бизнес-код» .

. Из этой информации , проще проектировать его приложение. Поэтому этот знаменитый «бизнес-код» будет содержаться в сервисе. Знайте, что наблюдаемые могут помочь вам!

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class BusinessService
{
  public mySharedData$: BehaviorSubject<Date> = new BehaviorSubject<Date>(new Date());
}

Этот сервис позволяет содержать логи c, деловую информацию и синхронизировать несколько компонентов, которые не являются родительскими / дочерними. Важно отметить, что данный сервис является одноразовым. Вы не должны добавлять его в таблицу провайдеров модуля. Если вы сделаете это, знайте, что у каждого компонента будет свой экземпляр этой службы, и результата не будет!


Компонент A:

import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

import { BusinessService } from './../business.service';

@Component({
  selector: 'app-component-a',
  templateUrl: './component-a.component.html',
  styleUrls: ['./component-a.component.css']
})
export class ComponentAComponent implements OnInit, OnDestroy
{
  public data: Date;

  private _destroy$: Subject<boolean> = new Subject<boolean>();

  public constructor(
    private _businessService: BusinessService
  ) { }

  public ngOnInit(): void
  {
    this._businessService
      .mySharedData$
      .pipe(takeUntil(this._destroy$))
      .subscribe(value => this.data = value);
  }

  public ngOnDestroy(): void
  {
    this._destroy$.next(true);
    this._destroy$.complete();
  }
}

Компонент B:

import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

import { BusinessService } from './../business.service';

@Component({
  selector: 'app-component-b',
  templateUrl: './component-b.component.html',
  styleUrls: ['./component-b.component.css']
})
export class ComponentBComponent implements OnInit, OnDestroy
{
  public data: Date;

  private _destroy$: Subject<boolean> = new Subject<boolean>();

  public constructor(
    private _businessService: BusinessService
  ) { }

  public ngOnInit(): void
  {
    this._businessService
      .mySharedData$
      .pipe(takeUntil(this._destroy$))
      .subscribe(value => this.data = value);
  }

  public ngOnDestroy(): void
  {
    this._destroy$.next(true);
    this._destroy$.complete();
  }
}

Это код для компонентов A и B. Мы внедряем BusinessService в различные компоненты и подписываемся на изменения значения свойства mySharedData, присутствующего в BusinessService, через метод ngOnInit. Механизм выглядит следующим образом:

  • Служба находится в памяти во время внедрения
  • Служба присваивает свойству mySharedData текущую дату и уведомляет подписчиков об изменении ( Различные компоненты).
  • Различные компоненты получают обновление и обрабатывают данные так, как они хотят.

На этом этапе вы можете синхронизировать значение между несколькими компонентами. Вы все еще должны понимать механизм обновления. Действительно, вы, например, захотите обновить это значение из компонента.

Давайте немного изменим код компонента B:

import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

import { BusinessService } from './../business.service';

@Component({
  selector: 'app-component-b',
  templateUrl: './component-b.component.html',
  styleUrls: ['./component-b.component.css']
})
export class ComponentBComponent implements OnInit, OnDestroy
{
  public data: Date;

  private _destroy$: Subject<boolean> = new Subject<boolean>();

  public constructor(
    private _businessService: BusinessService
  ) { }

  public ngOnInit(): void
  {
    this._businessService
      .mySharedData$
      .pipe(takeUntil(this._destroy$))
      .subscribe(value => this.data = value);
  }

  public ngOnDestroy(): void
  {
    this._destroy$.next(true);
    this._destroy$.complete();
  }

  public updateData(): void
  {
    this._businessService
      .mySharedData$
      .next(new Date());
  }
}

Вот и все! Новое значение будет добавлено в сервис, и различные компоненты будут уведомлены об изменении.

Я даю вам концепцию, вы должны работать над ней. Обратите внимание, что можно использовать канал asyn c для непосредственного управления подпиской на mySharedData в шаблонах компонентов.

Я, конечно, остаюсь доступным, если у вас есть какие-либо вопросы и / или комментарии.

Примечание: для получения чистого кода советую почистить подписки на уничтожение компонента. Я дал вам пример в этом направлении, чтобы дать вам идеи. (_destroy $ + pipe + takeUntil + ngOnDestroy).

До скорой встречи и удачи!

0 голосов
/ 14 апреля 2020

Один из возможных способов - использовать BehaviorSubject в общей службе.

private monthValueSubject = new BehaviorSubject<number>(-1);

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

import { Injectable } from "@angular/core";
import { Observable, BehaviorSubject } from "rxjs";

@Injectable()
export class SharedService {
  private monthValueSubject = new BehaviorSubject<number>(-1);

  constructor() {}

  setMonthValue(x: number) {
    this.monthValueSubject.next(x);
  }

  getMonthValueObservable(): Observable<number> {
    return this.monthValueSubject.asObservable();
  }
}

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

Внутри ваших компонентов требуются две базовые c вещи.

  ngOnInit() {
    this.sharedService.getMonthValueObservable().subscribe(x => {
      this.monthValue = x; // <-- this is where you get new values
    });
  }

  setMonthValue(x: number) {
    this.sharedService.setMonthValue(x); // <-- this is where you set new values
  }

Проверить это работает stackblitz .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...