我在组件的构造函数中使用以下代码。该组件正在使用
OnPush
变更检测策略。正如我们所看到的,setTimeout
在Angular区域之外执行,这意味着zonejs
不会知道setTimeout操作何时完成。
在这种情况下,谁通知 Angular 某些内容发生了变化并且应该触发变化检测周期?
我知道
markForCheck
负责将组件及其祖先标记为 dirty
,但我的困惑是:既然 setTimeout
在 Angular 区域之外运行,Angular 如何知道何时开始更改检测?
this.zone.runOutsideAngular(() => {
setTimeout(() => {
this.count = 5;
this.cdr.markForCheck();
}, 3000);
})
this.cdr.markForCheck()
与箭头函数一起使用,因为箭头函数没有自己的this
,它有对原始箭头函数的引用,由于我们已经标记为检查,Angular将运行一个变化检测循环,如果删除它,它不会运行更改检测。
如果你想知道如何查看
markForCheck
的内部源代码和Angular包。
更改检测 OnPush 仅在两种情况下触发:
OnPush 更改检测指示 Angular 仅在以下情况下对组件子树运行更改检测:
- 子树的根组件接收新输入作为模板绑定的结果。 Angular 使用 == 比较输入的当前值和过去值。
- Angular 会处理子树的根组件或其任何子组件中的事件(例如使用事件绑定、输出绑定或 @HostListener ),无论它们是否使用 OnPush 更改检测。
由于您的场景与这两种情况都不匹配,因此永远不会运行更改检测,除非您使用
ChangeDetectorRef
手动触发它。