棱角分明.为什么调用 markForCheck() 结果查看更新 [英] Angular. Why calling markForCheck() results to view update

查看:27
本文介绍了棱角分明.为什么调用 markForCheck() 结果查看更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

到处都说 markForCheck 只是将当前组件视图和所有父组件(直到根组件)标记为脏.所以下次 DetectChanges 执行时它会更新视图.从这一点上我有两个问题.在组件具有 changeDetection: ChangeDetectionStrategy.OnPush

的上下文中

1) 如果 'async pipe' 只调用 markForCheck (你可以看到 Rx 部分在 Angular/Zone 1 之后.

Angular 轮到他在执行异步回调时使用 zone 调用 tick() 函数.Tick 方法从根组件向下寻找标记以检查视图.

我在tick函数中设置了断点,它在我们的回调执行后被调用

那么当我们在模板上使用 async pipe 时,第一种情况会发生什么.

  1. 异步回调由异步管道操作符处理并调用 markForCheck() 函数
  2. 众所周知,markForCheck 将当前视图和父视图标记到 RootComponent 以供检查
  3. 在第 1 步的回调完成后,将调用 tick().最后将检查视图并更新它

第二种情况几乎相同,当我们在 RxJs 操作符中调用 markForCheck 时.我们和 async pipe 做同样的事情,因为我们的回调也用 zone 包裹,所以我们在回调完成后执行相同的过程.

如果您不会在异步回调中调用 markForCheck,而是调用 tick 函数,则不会进行任何更新.值得一提的是,如果您调用detectChanges(),即使没有调用markForCheck 函数,也会完成更新.这是 stackblitz 的示例这是由于 ChangeDetectorRef 中的 detechChanges 忽略了 markForCheck 标志,并对 Component 及其所有子项进行了更改检测.这篇文章中有更多细节

<块引用>

此方法会针对当前组件视图运行更改检测,而不管其状态如何

Everywhere it is said that markForCheck just marks current component view and all parent components (up to the root one) as dirty. So next time DetectChanges executes it will update the view. From this point I have 2 questions. Both in a context that component has changeDetection: ChangeDetectionStrategy.OnPush

1) If 'async pipe' does nothing but call markForCheck (source code), Why the view is updated?

2) If I try calling markForCheck inside some async process, the view will be updated as well.

The demo: stackblitz

Can you help me to understand what happens during these processes and why the view actually updated? I am expecting that someone call DetectChanges method after 1) and 2), but who...

解决方案

With help of @David I found the answer.

First things first, RxJs is not wrapped with zone anyhow, but native async functions are (as setTimer/Iterval, fetch api, XHR, DOM events). Because of RxJs timer/delay(...) operators use native async functions this causes them to be handled in a context of zone as well.

This is how the Callstack looks like when we are in the Rx tap operator

You can see that Rx part comes after Angular/Zone one.

Angular in his turn uses zone to call tick() function whenever async callback is executed. Tick method goes down from root component and looks for marked for checking views.

I put breakpoint in tick function, it is called after our callback is executed

So what happens in the first case when we use async pipe on the template.

  1. Async callback is handled by async pipe operator and markForCheck() function is called
  2. As we know markForCheck marks current and parent views up to the RootComponent for checking
  3. After callback from step 1 is done, the tick() is called. Which finally will check the view and update it

And almost the same happens in the second case, when we call markForCheck inside RxJs operator. We do the same thing as async pipe does, and because our callback is also wrapped with zone we have the the same process be executed after callback is done.

If you will not call markForCheck in your async callback, but call tick function, no update will be done. Worth mentioning that if you call detectChanges() the update will be done despite not calling markForCheck function. Here is the example on stackblitz This is due to detechChanges from ChangeDetectorRef ignores markForCheck flag and does change detection for Component and all its children. A lot more details in this article

This method runs change detection for the current component view regardless of its state

这篇关于棱角分明.为什么调用 markForCheck() 结果查看更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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