何时使用 Ngzone.run()?
Posted
技术标签:
【中文标题】何时使用 Ngzone.run()?【英文标题】:When to use Ngzone.run()? 【发布时间】:2018-12-29 12:48:07 【问题描述】:我在我的 Angular 项目中遇到了一个错误,最终通过将我的代码包装到中解决了
this.zone.run(() => /* my code here */);
如this 回答所述。
我之前对zone
的理解是,angular无法检测到第三方库的异步callbacks
所做的更改,因为“它们不在angular的zone
中”。如果我单击button
,则触发的事件不是浏览器的本机click
事件,而是由angular 创建的自定义(已修补)click
事件,其handler
在zone
中运行,因此 angular 知道其回调处理程序所做的更改。
但我无法理解通过在第三方回调中运行router.navigate()
会产生此问题(如this github 问题所示)。 Router
不是 Angular 本身的 service
吗?为什么在第三方callback
调用时不自动通知angular的zone
?
我在 NGXS 的 state reducer 中使用 router.navigate
遇到了这个问题。
我的问题是:
谁能解释一下我什么时候需要将我的代码包装在NgZone
中?
调试了几个小时并意识到我的代码超出了zone
上下文是很烦人的。
【问题讨论】:
@dasfsa,如果事件不在“角度区域”中,角度无法检测到该事件。换句话说,Angular 可以检测到 router.navigate,但无法检测到执行 router.navigate 的事件 doc 中提供的示例确实解释了它的用法:angular.io/api/core/NgZone#example 我正在解决一些将我引导到这个 NgZone 的问题。我需要从 iframe 外部的脚本更新组件内部的属性。 我把演示放在这里:stackblitz.com/edit/… 我发现在async
函数中导航时需要this.ngZone.run(() => this.router.navigate(["login"])).then();
。
【参考方案1】:
ngZone.runOutsideAngular() - 这会在角度区域之外运行代码。
当某个事件被触发时,它会告诉 Angular 来检测变化。 如果您使用的是 mouseUp() 或 mouseDown() 事件,那么在每次更改时它都会告诉 Angular 来检测更改。 如果我们不希望这些更改在 Angular 运行时发生(这会降低应用的性能),我们可以在 Angular 区域之外运行它。 与此相反,如果我们非常想获得每一个更新,那么我们可以使用 ngZone.run()。表示它将正常运行更改检测。Angular 本身在后台使用 ngZone 来检测变化
所以,如果我们已经离开了角度区域,那么我们使用ngZone.run()
返回来
【讨论】:
【参考方案2】:ngZone.run()
在对路由进行单元测试时特别有用。
it('should redirect if condition true, fakeAsync(() =>
router.navigate(['']);
fixture.ngZone.run(() =>
component.redirectIfConditionTrue();
);
tick();
expect(location.path()).toBe('/AgentLeadsManager');
));
来源:这是我唯一一次使用它
【讨论】:
【参考方案3】:Zone.js 是用于跟踪和拦截异步操作的执行上下文 比如:DOM 事件(
click
、keydown
、keyup
、etc
)、setTimeout
、setInterval
。XMLHttpRequest
s)
NgZone 只是 Zone.js
的 API 的包装 Angular 服务。
Angular 团队决定在使用 Angular 时需要执行上下文的抽象,因此他们在 Angular 中围绕它构建了 Zone.js 和包装器(非正式地 - 适配器模式)。
所以基本上回答你的问题:在处理与 Zone.js 中的 Angular 运行上下文无关的任何类型的第 3 方库时(除非你决定不需要执行上下文并且你可以工作 without 它使用NoopNgZone
)
Source
【讨论】:
以上是关于何时使用 Ngzone.run()?的主要内容,如果未能解决你的问题,请参考以下文章