#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>