Angular markForCheck 与 detectChanges

Angular markForCheck vs detectChanges

我将从 我在 Whosebug 上看到类似问题的概念开始这个问题,但该问题只回答了 差异.

我要问的是我应该根据情况使用什么一种或另一种方法可能有什么缺点

我知道 detectChanges 运行 对元素及其子元素的即时变化检测周期,同时 markForCheck 仅将当前元素及其祖先标记为脏元素,并且它们应该是检查下一个变化检测周期。

我问这个主要是因为我觉得我不应该总是在异步调用中使用 markForCheck

例如,我有一个 InputComponent,它是常规 HTML 输入的包装器。此 InputComponent 已启用 ChangeDetectionStrategy.OnPush

当我对服务器进行异步调用并获取数据时,我需要 运行 对该 InputComponent 的更改检测来更新选项列表,对此我有两个选项。

首先(我觉得我应该使用的)是 detectChanges,因为它只会对这个确切的组件应用检查,而 markForCheck 会导致检查整个树分支。

那么我应该使用什么以及我是否需要使用 markForCheck 以及为什么?

What I'm asking is what should I use depending on situation and what drawbacks one or another method may have.

你应该永远不要调用detectChanges()

detectChanges() 为开发人员提供价值的情况并不理想。它通常用在程序员没有很好地管理组件的不可变性、状态管理和变异的项目中。

所有需要 detectChanges() 的源代码都可以重写,这样就不需要了。

另一方面,markForCheck() 确实有很好的边缘情况,应该使用它。

I'm asking this mostly because I don't feel like I should always use markForCheck in async calls.

您经常会在调用 markForCheck().

的源代码附近找到对 this 的引用
@Component({...})
export class ExampleComponent {
    //......
    public function work() {
        this.httpClient.get(...).subscribe(resp => 
            this.data = resp.data;
            this.changeDetectorRef.markForCheck();
        });
    }
}

在函数式编程中,对 this 的引用是 不纯的 并且会改变函数范围之外的外部状态。打破函数式编程最佳实践会引入需要修复 才能使一切正常运行的问题。如果您只编写带有异步操作的纯函数,则永远不必调用 markForCheck(),但是一旦引入 this 引用,组件状态就会发生变化,并且需要通知视图。

以上没有任何问题,但同时在 RxJS 订阅中过度使用 this 会创建难以维护的源代码。

最好重写源代码以使用响应式编程,并在模板中使用 async 管道。关键是创建 无状态 的组件,以便不需要更新组件上的属性。一切都作为反应流完成。

@Component({
    template: `<ng-container *ngIf="data$ | async as data">
               <!-- stuff -->
               </ng-container>`,
    // .....
})
export class ExampleComponent {
    public data$: Observable<any>;

    public function work() {
        this.data$ = this.httpClient.get(...).pipe(shareReplay(1));
    }
}

如果您将组件设计为 无状态 并使用 RxJS 进行所有数据处理,那么应该不需要使用 markForCheck()。即使您监听 DOM 事件,数据也可以通过管道传输到其他可观察对象,以避免使用 this.

虽然有时您必须调用 markForCheck()。我建议您停止并重新考虑避免使用它的方法,因为应该有另一种不需要它的方法。