Angular markForCheck 与 detectChanges

Ser*_*gey 7 performance typescript angular angular-changedetection

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

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

我知道detectChanges在一个元素及其子元素上运行即时更改检测周期,同时markForCheck只将当前元素及其祖先标记为脏,并且应该在下一个更改检测周期中检查它们。

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

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

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

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

那么我应该使用什么,我需要使用markForCheck什么,为什么?

Rea*_*lar 5

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

永远不应该打电话detectChanges()

没有一个好的边缘情况可以detectChanges()为开发人员提供价值。它通常用在程序员未能很好地管理组件的不变性、状态管理和突变的项目中。

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

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

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

您经常会找到对this调用markForCheck().

@Component({...})
export class ExampleComponent {
    //......
    public function work() {
        this.httpClient.get(...).subscribe(resp => 
            this.data = resp.data;
            this.changeDetectorRef.markForCheck();
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

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

上面的内容并没有什么问题,但同时过度使用thisRxJS 订阅会导致源代码难以维护。

最好重写源代码以使用反应式编程,并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));
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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