Angular 2, 使用 ngZone.runOutsideAngular 和 requestAnimationFrame 循环

Angular 2, using ngZone.runOutsideAngular with a requestAnimationFrame loop

根据我在网上阅读的内容,Angular 团队建议您始终在 Angular 区域之外调用 requestAnimationFrame(),如下所示:

this.ngZone.runOutsideAngular(() => {
  requestAnimationFrame(timestamp => {
    let timerStart = timestamp || new Date().getTime();
    this.myAnimeMethod(timestamp);
  });
});

但是循环呢...

this.ngZone.runOutsideAngular(() => {
  requestAnimationFrame(timestamp => {
    let timerStart = timestamp;
    this.myAnimeMethod(timestamp, timerStart);
  });
});

myAnimeMethod(timestamp, timerStart) {
  let time = timestamp || new Date().getTime();
  let runtime = time - timerStart;

  /// animation logic here

  if(runtime < 10000) {

    // ------- continue to animate for 10 seconds -- //

    requestAnimationFrame(timestamp => {
      this.myAnimeMethod(timestamp, timerStart);
    });
  }
}

在第一次请求时调用 this.ngZone.runOutsideAngular() 是否足够,还是我应该像这样在 myAnimeMethod() 中再次调用 this.ngZone.runOutsideAngular()

this.ngZone.runOutsideAngular(() => {
  requestAnimationFrame(timestamp => {
    let timerStart = timestamp;
    this.myAnimeMethod(timestamp, timerStart);
  });
});

myAnimeMethod(timestamp, timerStart) {
  let time = timestamp || new Date().getTime();
  let runtime = time - timerStart;

  /// animation logic here

  if(runtime < 10000) {

    // ------- request to run outside of Angular again while continuing to animate for 10 seconds -- //

    this.ngZone.runOutsideAngular(() => {
      requestAnimationFrame(timestamp => {
        this.myAnimeMethod(timestamp, timerStart);
      });
    });

  }
}

简短回答:您不需要继续从来自 Angular.

外部调用的 requestAnimationFrame 处理程序调用 NgZone.runOutsideAngular

长答案:一旦你进入 "root" 区域(这是你调用 NgZone.runOutsideAngular 时得到的),任何 requestAnimationFrame 回调也将 运行来自那个区域,除非你明确请求一个不同的区域,例如通过 NgZone.run.

要检查这一点,请尝试从您的 requestAnimationFrame 处理程序调用静态函数 NgZone.isInAngularZone()

请注意,我使用 Angular 4.4.4 和 Zone.js 0.8.18 进行了测试。

您还可以创建一个 ngzon-flags.ts,将所有异常用于更改检测。

// All events inside the BLACK-LIST Array will not trigger updates anymore from angular
// requestAnimationFrame wont trigger change detection
(window as any).__Zone_disable_requestAnimationFrame = true; 
// Same for scroll and mousemove or any other event youll add
(window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove'];

将该文件导入您的 polyfills.ts:

import './ngzone-flags'