Используйте наблюдаемое хранилище и компонентный ввод с Angular

#angular #rxjs #store

#angular #rxjs #Магазин

Вопрос:

Я разработал собственное хранилище angular, используя a BehaviorSubject , и я использую вот так:

 export class UserFaceComponent {

    @Input()
    public id: any;

    public presence$: Observable<boolean>;

    constructor(private _store: Store) { }

    public ngOnInit() {
        this.presence$ = this._store
            .select(s => s.users.presences)
            .pipe(
                map(p => p.includes(this.id))
            );
    }
}
  

Таким образом, при изменении хранилища presence$ наблюдаемое выдает новое значение. Он работает хорошо, однако id передаваемый компоненту также может измениться. Допустим, на странице есть список пользователей, и когда пользователь выбирает одного из них, он обновляет переменную selectedUserId , которая передается в UserFaceComponent . Это будет тот же компонент, что и раньше, но id он будет обновлен.

Это означает, что я должен создать тему в своем компоненте, подписаться на onChange перехват и отправлять по этой теме при изменении идентификатора. Затем я должен объединить это наблюдаемое с приведенным выше, а затем выдать новое значение.

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

Ответ №1:

Я несколько раз сталкивался с одним и тем же требованием, и, к сожалению, нет более простого решения, чем ваш onChange subject подход. Я читал однажды, что было предложение ObservableInput декоратора, но оно так и не было реализовано.

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

 private _id: BehaviorSubject<string> = new BehaviorSubject<string>();
@Input()
set id(value: string) {
  this._id.next(value);
}
get id(): string {
 return this._id.value;
}
  

Комментарии:

1. Не совсем тот ответ, который я искал (я надеялся на волшебное решение, я думаю, хе-хе), но эта версия короче моей. Спасибо

Ответ №2:

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

 export class UserFaceComponent {

    @Input()
    public id: any;

    public presence$: Observable<boolean>;

    constructor(private _store: Store) { }

    ngOnChanges(changes: SimpleChanges) {
      if (changes['id']) {
        const currentId = changes['id'].currentValue
        this.presence$ = this._store
          .select(s => s.users.presences)
          .pipe(
            map(p => p.includes(currentId))
          );
      }
    }
}
  
 <div>{{ presence$ | async }}</div>