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'
根据我在网上阅读的内容,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'