我将从我在StackOverflow上看到过类似问题的想法开始这个问题,但是该问题只能解决差异。
我要问的是,我应该根据情况使用什么和,一种或另一种方法可能具有的缺点。
我知道detectChanges
在元素及其子元素上立即执行更改检测周期,而markForCheck
仅将当前元素及其祖先标记为脏,并且应在下一个更改检测周期中对其进行检查。
我之所以这样问,主要是因为我不认为我应该始终在异步调用中使用markForCheck
。
例如,我有一个InputComponent
,它是常规HTML输入的包装器。此InputComponent
已启用ChangeDetectionStrategy.OnPush
。
当我对服务器进行异步调用并获取数据时,我需要在该InputComponent
上运行更改检测以更新选项列表,对此我有两个选项。
首先(我觉得我应该使用的)是detectChanges
,因为它将仅对此确切的组件应用检查,而markForCheck
将导致对整个 Twig 进行检查。
那么,我应该使用什么?我需要使用markForCheck
吗?为什么?
最佳答案
您应该永远不要调用detectChanges()
。detectChanges()
没有为开发人员提供值(value)的优势。它通常用在程序员无法很好地管理其不变性,状态管理和组件变更的项目内部。
所有需要detectChanges()
的源代码都可以重写,因此不是必需的。
另一方面,markForCheck()
确实有应使用的边缘情况。
您经常会在调用this
的源代码附近找到对markForCheck()
的引用。
@Component({...})
export class ExampleComponent {
//......
public function work() {
this.httpClient.get(...).subscribe(resp =>
this.data = resp.data;
this.changeDetectorRef.markForCheck();
});
}
}
在函数式编程中,对
this
的引用是不纯的,并且会使函数范围之外的外部状态发生变化。脱离函数式编程最佳实践的做法引入了一些问题,需要对其进行修复才能使一切正常运行。如果您仅使用异步操作编写纯函数,则无需调用markForCheck()
,但是一旦引入了this
引用,组件状态就会发生变化,并且需要通知 View 。上面没有任何问题,但是与此同时,RxJS订阅中对
this
的过度使用产生了难以维护的源代码。最好重写源代码以使用响应式(Reactive)编程,并在模板中使用
async
管道。关键是要创建无状态的组件,从而无需更新组件上的属性。一切都作为 react 流完成。@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()
。我建议您停止并重新思考避免使用该方法的方法,因为应该有另一种不需要它的方法。