Привязать к @Output Наблюдаемое вместо обратного вызова?

У меня есть компонент слайдера, который испускает числа при перетаскивании ползунка, который можно использовать следующим образом: <my-slider (change)="onSlide($event)"></my-slider>. Я хотел бы избавиться от метода onSlide и вместо этого привязать поток событий change к свойству Observable<number> (вместо обратного вызова).

Я использую Angular 2 EventEmitter для моего @Output. EventEmitter наследуется от RxJs Subject, который является Observable и Observer. Я хочу повторно использовать сторону Observable EventEmitter.

Конечно, я могу передать значения, которые вводятся через onSlide на другой Subject, но я хочу предотвратить этот шаблон и накладные расходы. Есть ли способ?

Ответы

Ответ 1

Одно из основных различий между Angular 1 и Angular 2 заключается в том, что обнаружение изменений всегда выполняется сверху вниз. Это делает работу намного лучше. Также нет необходимости выполнять "стабилизацию" ($ digest loop), как это было в Angular 1.

В Angular 2 вы не можете "нажимать" изменение другим способом, за исключением испускания события с EventEmitter/Subject, поэтому Angular 2 может начать проверку компонентов Change Detectors.

Вот хорошая статья об этой теме.

Ответ 2

Не уверен, что релевантно или если это кому-то помогает: у меня возникла аналогичная проблема: я хотел использовать свойство типа Observable<number>, предоставляемое компонентом в родительском компоненте.

После чтения Observables and Reactive Programming в Angular 2 я заметил, что мне нужно "обернуться" вокруг моей архитектуры и позволить parent создайте Observable, а затем назначьте его дочернему элементу.

Поэтому вместо того, чтобы иметь MyComponent с @Output() типа Observable<number> (который затем был инициализирован до new BehaviorSubject(0) и изменен с использованием вызовов next), я изменил MyComponent на haven a @Input() типа BehaviorSubject<number>:

@Component({
  selector: 'my-component',
  template: `
    <button (click)="increment()">Click me!</button>
  `,
})
export class MyComponent {
  private _count : number = 0;

  @Input()
  public counter : BehaviorSubject<number>;

  public increment() {
    this._count++;

    if (this.counter)
      this.counter.next(this._count);
  }
}

Теперь родитель создает объект BehaviorSubject и привязывается к свойству. Он может легко использовать объект BehaviorSubject как наблюдаемый:

@Component({
  selector: 'my-app',
  template: `
    <my-component [counter]="count"></my-component>
    <span>{{text | async}}</span>
  `,
})
export class App {
  public text : Observable<string>;

  public count : BehaviorSubject<number> = new BehaviorSubject(0);

  constructor() {
    this.text = this.count.map(n => "Click: " + n);
  }
}

Plunker: https://plnkr.co/edit/rKtVWmmGnFn4Po4B4CCL?p=preview

Итак, в вашем случае я бы сказал, что ваш слайдер должен предоставить @Input (может быть, назвать его значением или номером) и позволить родительскому объекту назначать наблюдаемое (вместо того, чтобы позволить ребенку создать его).