gpt4 book ai didi

javascript - Angular - RxJS : afterViewInit and Async pipe

转载 作者:行者123 更新时间:2023-12-01 16:17:25 24 4
gpt4 key购买 nike

我尝试在使用 changeDetection: ChangeDetectionStrategy.OnPush, 的组件中执行以下操作

@ViewChild('searchInput') input: ElementRef;

ngAfterViewInit() {
this.searchText$ = fromEvent<any>(this.input.nativeElement, 'keyup')
.pipe(
map(event => event.target.value),
startWith(''),
debounceTime(300),
distinctUntilChanged()
);
}

并且在模板中
<div *ngIf="searchText$ | async as searchText;">
results for "<b>{{searchText}}</b>"
</div>

它不起作用,但是如果我删除 OnPush ,确实如此。我不太清楚为什么,因为异步管道应该触发更改检测。

编辑 :

按照答案,我试图用以下内容替换我所拥有的:
this.searchText$ = interval(1000);

没有任何 @Input , async管道正在标记我的组件以供检查,它工作得很好。所以我不明白为什么我没有与 fromEvent 相同的行为

最佳答案

默认情况下,每当 Angular 启动更改检测时,它都会一个一个地检查所有组件并检查是否有某些内容发生了变化,如果是,则更新其 DOM。当您将默认更改检测更改为 ChangeDetection.OnPush 时会发生什么?

Angular 改变了它的行为,只有两种方法可以更新组件 DOM。

  • @Input 属性引用已更改
  • 手动调用 markForCheck()

  • 如果您执行其中一项操作,它将相应地更新 DOM。在您的情况下,您不使用第一个选项,因此您必须使用第二个并调用 markForCheck() ,任何地方。但是有一种情况,每当您使用异步管道时,它都会为您调用此方法。

    The async pipe subscribes to an Observable or Promise and returns the latest value it has emitted. When a new value is emitted, the async pipe marks the component to be checked for changes. When the component gets destroyed, the async pipe unsubscribes automatically to avoid potential memory leaks.



    所以这里没有什么神奇的,它调用 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
    }

    因此,如果传递的值不是未定义的,它将订阅该 observable 并采取相应的行动(调用 markForCheck() ,无论何时发出值)

    现在是最关键的部分
    Angular 第一次调用 transform 方法时,它是未定义的,因为你初始化了 searchText$里面 ngAfterViewInit()回调( View 已经渲染,所以它也调用异步管道)。所以当你初始化 searchText$字段,该组件的变更检测已经完成,所以它不知道 searchText$已被定义,随后它不再调用 AsyncPipe,所以问题是它永远不会让 AsyncPipe 订阅这些更改,你要做的是调用 markForCheck()初始化后仅一次,Angular 再次在该组件上运行 changeDetection,更新 DOM 并调用 AsyncPipe,它将订阅该 observable
    ngAfterViewInit() {
    this.searchText$ =
    fromEvent<any>(this.input.nativeElement, "keyup").pipe(
    map((event) => event.target.value),
    startWith(""),
    debounceTime(300),
    distinctUntilChanged()
    );
    this.cf.markForCheck();
    }

    关于javascript - Angular - RxJS : afterViewInit and Async pipe,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62443972/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com