角度markForCheck与detectChanges [英] Angular markForCheck vs detectChanges

查看:71
本文介绍了角度markForCheck与detectChanges的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将从一个问题开始,这个问题是我在StackOverflow上看到了一个类似的问题,但是这个问题只能解决差异.

I'll start this question from notion that I've seen a similar question on StackOverflow, but that question had only answer for the difference.

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

我知道 detectChanges 在元素及其子元素上立即执行更改检测周期,而 markForCheck 仅将当前元素及其祖先标记为脏元素,应该对其进行检查在下一个变更检测周期中.

I know that detectChanges runs immediate change detection cycle on an element and its children, meanwhile markForCheck only marks current element and its ancestors as dirty and that they should be checked on the next change detection cycle.

我之所以问这个问题,主要是因为我不认为我应该在异步调用中始终使用 markForCheck .

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

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

For example I have an InputComponent which is a wrapper for a regular HTML input. This InputComponent has ChangeDetectionStrategy.OnPush enabled.

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

When I make an asynchronous call to the server and get the data I need to run the change detection on that InputComponent to update a list of options and I have two options for that.

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

First (what I feel I should be using) is detectChanges because it would apply checks only for this exact component, whilst markForCheck would cause the whole tree branch to be checked.

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

So what should I use and do I need to use markForCheck ever and why?

推荐答案

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

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

您应该从不呼叫 detectChanges().

detectChanges()为开发人员提供价值方面没有一个很好的例子.它通常用在那些项目的不可变性,状态管理和组件的变异没有被程序员很好地管理的项目内部.

There isn't a good edge case where detectChanges() offers value to the developer. It's usually used inside projects where immutability, state management and mutation of the component have not been well managed by the programmer.

所有需要 detectChanges()的源代码都可以重写,因此不是必需的.

All source code that needs detectChanges() can be rewritten so that it's not required.

另一方面, markForCheck()确实有应使用的边缘情况.

On the other hand, markForCheck() does have good edge cases where it should be used.

我之所以问这个问题,主要是因为我不认为我应该始终在异步调用中使用markForCheck.

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

您经常会在调用 markForCheck()的源代码附近找到对该 this 的引用.

You will often find a reference to this near source code that calls markForCheck().

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

在函数式编程中,对 this 的引用是不纯,并且使函数范围之外的外部状态发生变化.脱离函数式编程最佳实践的做法引入了一些问题,需要进行修复才能使一切正常运行.如果您仅使用异步操作编写纯函数,则不必调用 markForCheck(),但是一旦引入了 this 引用,组件状态就会发生变化,并且视图需要被通知.

In functional programming, a reference to this is impure and mutates an external state outside the scope of the function. Breaking from functional programming best practices introduces problems that require fixes to keep everything working. If you write only pure functions with your async operations you never have to call markForCheck(), but once you introduce a this reference the components state is mutated and the view needs to be notified.

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

There is nothing wrong with the above, but at the sametime excessive usage of this in RxJS subscriptions creates source code that can be difficult to maintain.

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

It's better to rewrite your source code to use reactive programming, and use the async pipe in the template. The key is to create components that are stateless so that a properties on the component don't need to be updated. Everything is done as a reactive stream.

@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 .

If you design your components to be stateless and use RxJS for all of your data processing, then there shouldn't be a requirement to use markForCheck(). Even when you listen for DOM events the data can be piped to other observables to avoid using this.

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

While there will be times when you have to call markForCheck(). I recommend that you stop and rethink your approach to avoid the use of it, because there should be another way that doesn't require it.

这篇关于角度markForCheck与detectChanges的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆