我试着阅读很多关于角度2的区域。我知道角度使用zone.js进行变化检测。我看到一些代码使用了zone.run并在其中放置了一些操作。它实际上做了什么?我理解的一件事是它将这些命令作为单独的块执行。我仍然无法弄清楚zone.run的实际用途
答案 0 :(得分:5)
要详细了解NgZone
阅读:
它实际上做了什么?
Zone.run
可让您更改当前区域。这是基本的例子:
console.log(Zone.current.name); // <root>
setTimeout(() => console.log(Zone.current.name)); <root>
// we're in the <root> zone now, but when we call `run` on the instance of zone `A` we change the zone
Zone.current.fork({name: 'A'}).run(() => {
console.log(Zone.current.name); // A
setTimeout(() => console.log(Zone.current.name)); // A
});
// again we're back in the <root> zone now, but when we call `run` on the instance of zone `B` we change the zone
Zone.current.fork({name: 'B'}).run(() => {
console.log(Zone.current.name); // B
setTimeout(() => console.log(Zone.current.name)); // B
});
Zone.current.fork
创建一个新区域。它返回对此新区域的引用,并使用run
您可以在此区域内执行异步操作。您可以在上面看到setTimeout
异步任务在整个时间内保持正确的区域。
Angular创建了自己的区域:
function forkInnerZoneWithAngularBehavior(zone: NgZonePrivate) {
zone._inner = zone._inner.fork({
name: 'angular',
properties: <any>{'isAngularZone': true},
...
当你将NgZone
注入类构造函数时,这个新区域就是你所获得的:
constructor (zone: NgZone) {}
当前执行区不是Angular zone(NgZone) - zone.run()
时,您需要使用Zone.current.name !== 'angular'
。如果是这种情况,您需要Angular不会选择从此区域安排的所有异步任务,并且它不会安排更改检测。因此,您可以切换到Angular区域以执行某些异步任务:
Zone.current.fork({name: 'A'}).run(() => {
// this timeout won't be picked up by Angular
setTimeout(() => console.log(Zone.current.name)); // A
// this timeout will be picked up by Angular
NgZone.run(() => setTimeout(() => console.log(Zone.current.name)));
});
有时您也可能会执行相反操作并在Angular区域外运行一些异步任务。使用runOutsideAngular
方法:
NgZone.runOutsideAngular(()=>{ ... })
答案 1 :(得分:3)
什么是Zone.js?
区域是在异步任务中持续存在的执行上下文。您可以将其视为JavaScript VM的线程本地存储。
它是如何运作的?
zone.js修补大多数标准Web API(例如DOM事件,XMLHttpRequest ...)和nodejs API(EventEmitter,fs ...)。
它如何应用于Angular?
Angular依赖于Zone.js修补浏览器事件,以便在事件完成后触发更改检测。这允许您使用POJO(普通的旧javascript对象)。
注意:如果您想查看补丁浏览器事件的示例,请尝试执行alert(setTimeout)
您可能希望使用Zone.run
手动触发Angular不知道的异步事件的更改检测。例如,您可以将Zone.run
用于从第三方组件触发的自定义事件。