到处都说 markForCheck 只是将当前组件视图和所有父组件(直到根组件)标记为脏组件。因此,下次 DetectChanges 执行时,它将更新视图。
从这一点上我有两个问题。两者都在该组件具有的上下文中changeDetection: ChangeDetectionStrategy.OnPush
1) 如果“async pipeline”除了调用 markForCheck (源代码 https://github.com/angular/angular/blob/master/packages/common/src/pipes/async_pipe.ts#L143),为什么视图会更新?
2)如果我尝试在某个异步进程中调用markForCheck,视图也会更新。
演示:堆栈闪电战 https://stackblitz.com/edit/angular-9-starter-material-p3eggx
您能帮助我了解这些过程中发生的情况以及视图实际更新的原因吗?我期待有人在 1) 和 2) 之后调用 DetectChanges 方法,但是谁......
在@David 的帮助下我找到了答案。
首先,RxJs 无论如何都没有用区域包装,但本机异步函数是(如setTimer/Iterval
, fetch
api, XHR
, DOM events
)。由于 RxJs 定时器/延迟(...) 运算符使用本机异步函数,这导致它们也在区域上下文中进行处理。
这就是我们在 Rx 中时 Callstack 的样子tap
操作员
You can see that Rx part comes after Angular/Zone one.
Angular轮到他了使用区域呼叫tick()
每当执行异步回调时函数。Tick
方法从根组件向下查找标记为检查视图。
我在tick函数中放置了断点,它在我们的回调执行后被调用
那么当我们使用第一种情况时会发生什么async pipe
在模板上。
- 异步回调由异步管道运算符处理,并调用 markForCheck() 函数
- 正如我们所知,markForCheck 将当前视图和父视图标记为 RootComponent 进行检查
- 步骤 1 的回调完成后,
tick()
叫做。最后将检查视图并更新它
当我们调用第二种情况时,几乎相同的情况发生markForCheck
在 RxJs 运算符内。我们做同样的事情async pipe
确实如此,并且因为我们的回调也用区域包装,所以我们在回调完成后执行相同的过程。
如果您不在异步回调中调用markForCheck,而是调用tick函数,则不会进行任何更新。
值得一提的是,如果您调用 detectorChanges(),尽管没有调用 markForCheck 函数,更新也会完成。
这是关于的示例堆栈闪电战 https://stackblitz.com/edit/angular-9-starter-material-boqk4e?file=src/app/app.component.ts这是由于 ChangeDetectorRef 中的 detechChanges 忽略了 markForCheck 标志,并对组件及其所有子组件进行更改检测。
这里面还有很多细节article https://hackernoon.com/everything-you-need-to-know-about-change-detection-in-angular-8006c51d206f
此方法对当前组件视图运行更改检测,无论其状态如何
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)