По умолчанию Каждый раз, когда Angular запускает обнаружение изменений, он просматривает все компоненты один за другим и проверяет, не изменилось ли что-то, и обновляет свою DOM, если это так. что произойдет, если вы измените определение изменений по умолчанию на ChangeDetection.OnPush
?
Angular изменяет свое поведение, и есть только два способа обновить компонентную DOM.
Если вы выполните одно из этих действий, DOM обновится соответствующим образом. в вашем случае вы не используете первый вариант, поэтому вам придется использовать второй и звонить markForCheck()
в любом месте. но есть один случай, когда вы используете конвейер asyn c, он будет вызывать этот метод для вас.
Канал asyn c подписывается на Observable или Promise и возвращает последнее значение, которое оно испустил. Когда выдается новое значение, асинхронный конвейер отмечает компонент, подлежащий проверке на наличие изменений . Когда компонент разрушается, конвейер asyn c автоматически отменяет подписку, чтобы избежать потенциальных утечек памяти.
, поэтому здесь нет ничего magi c, он вызывает markForCheck()
под капотом. но если это так, почему ваше решение не работает? Чтобы ответить на этот вопрос, давайте углубимся в сам AsyncPipe. если мы проверим исходный код функции преобразования AsyncPipes, выглядит так:
transform(obj: Observable<any>|Promise<any>|null|undefined): any {
if (!this._obj) {
if (obj) {
this._subscribe(obj);
}
this._latestReturnedValue = this._latestValue;
return this._latestValue;
}
....// some extra code here not interesting
}
, поэтому, если переданное значение не является неопределенным, она подпишется на этот наблюдаемый объект и будет действовать соответствующим образом (вызовите markForCheck()
при появлении значения)
Теперь самая важная часть. первый раз Angular вызывает метод преобразования, он не определен, потому что вы инициализируете searchText$
внутри ngAfterViewInit()
обратного вызова (представление уже визуализировано, поэтому он также вызывает asyn c pipe). Итак, когда вы инициализируете поле searchText$
, обнаружение изменений уже завершено для этого компонента, поэтому он не знает, что searchText$
был определен, и впоследствии он больше не вызывает AsyncPipe, поэтому проблема в том, что он никогда не получает к AsyncPipe, чтобы подписаться на эти изменения, вам нужно вызвать markForCheck()
только один раз после инициализации, Angular снова запустить changeDetection для этого компонента, обновить DOM и вызвать AsyncPipe, который будет подписываться на этот наблюдаемый
ngAfterViewInit() {
this.searchText$ =
fromEvent<any>(this.input.nativeElement, "keyup").pipe(
map((event) => event.target.value),
startWith(""),
debounceTime(300),
distinctUntilChanged()
);
this.cf.markForCheck();
}