什么时候使用 zone.run()?

When to use zone.run()?

我试图在 angular 中阅读很多关于 NgZone 的内容。我知道 angular 使用 zone.js 进行变化检测。我看到一些代码使用了 zone.run 并在其中放置了一些操作。

它实际上是做什么的?

还是想不通zone.run

的实际用途
this.zone.run(() => {
     /* my code here */
});

借助这个link,我明白了一些。

答案本身在您提到的博客中提供。我会尝试进一步分解它。在 given example 中:

Situation: You are creating a progress-bar component whose value will be updated every 10 milli seconds

没有NgZone:

单击 button 后,将使用函数调用 increaseProgress()(进度条完成后将显示其值)

    <button (click)="processWithinAngularZone()">
      Process within Angular zone
    </button>

它每 10 毫秒调用一次,并不断增加 this.progress 计数器直到 100

increaseProgress(doneCallback: () => void) {
  this.progress += 1;
  console.log(`Current progress: ${this.progress}%`);

  if (this.progress < 100) {
    window.setTimeout(() => {
      this.increaseProgress(doneCallback);
    }, 10);
  } else {
    doneCallback();
  }
}

这会起作用,但是 因为我们使用的是 setTimeoutChangeDetection 周期将每隔 10 milliseconds 触发一次,这将影响性能申请


NgZone:

ngZone 我们正在通过,zone.run() 而不是 console.log。一旦计数器完成,这基本上将作为 ChangeDetection 的触发器。

现在,为了避免 setTimeout 效果(由于猴子修补而触发 ChangeDetection,我们将整个执行块包装在 this.zone.runOutsideAngularChangeDetection 仅在我们显式调用 zone.run().

时调用
  this.zone.runOutsideAngular(() => {
    this.increaseProgress(() => {
      this.zone.run(() => {
        console.log('Outside Done!');
      });
    });
  });

类似用例:

  1. 假设您需要在 scrollEvent 上实现一些逻辑,这可能会触发一个可能导致触发 ChangeDetection 的函数。为避免这种情况,我们可以使用 zone.runOutsideAngular 并在某些 action/duration 之后使用 zone.run().

    手动触发 ChangeDetection
  2. 您正在使用一些第 3 方库(它在 Angular ChangeDetection 之外工作)并且您需要在第 3 个事件发生后手动触发 CD派对图书馆。

它不是很频繁地使用它,但是,是的,它会在不为人知的情况下产生不需要的行为。

我希望它能帮助您更好地理解这个概念