0%

angular-run-outside-angular

runOutsideAngularNgZone的一个方法,它接受一个函数作为参数,该函数会在Angular的NgZone之外执行。这个方法的作用是什么呢?

runOutsideAngular函数中运行的代码不会触发Angular变更检测。这里的outside并不是真的在Angular之外运行,而是在Angular的Zone之外运行。

  1. 在执行一些性能敏感的操作时,比如处理大量DOM事件或者动画,避免频繁的变更检测导致性能问题。比如,如果有一个画布应用,用户拖动元素的时候,每次mousemove事件都触发变更检测可能不太高效,这时候用runOutsideAngular可以让这些事件处理在Angular Zone外运行,减少不必要的检测。

  2. 第三方库的集成,比如使用D3.js或者Three.js这些库,它们可能有自己的渲染循环,这时候用runOutsideAngular可以避免Angular的变更检测干扰这些库的性能。

  3. 另外,长时间运行的计算任务,比如Web Worker中的处理,可能也需要用这个方法,确保这些任务不会触发变更检测,直到真正需要更新UI的时候再手动触发。

所有上面这些情况都需要用到runOutsideAngular方法,它可以让我们更好地控制变更检测的时机,避免不必要的性能损耗。

频繁的DOM操作

1
2
3
4
5
6
7
8
9
10
11
12
13
import { Component, NgZone } from '@angular/core';

@Component({...})
export class CanvasComponent {
constructor(private ngZone: NgZone) {
ngZone.runOutsideAngular(() => {
canvasElement.addEventListener('mousemove', (event) => {
// 处理鼠标移动,不触发变更检测
this.updateCanvasPosition(event);
});
});
}
}

集成第三方库

1
2
3
4
5
6
7
ngZone.runOutsideAngular(() => {
const chart = d3.select('#chart');
chart.on('zoom', () => {
// D3 的缩放操作,避免 Angular 频繁检查
this.handleZoom();
});
});

Web workers或耗时计算

1
2
3
4
5
6
7
ngZone.runOutsideAngular(() => {
const worker = new Worker('data-processor.worker.ts');
worker.onmessage = (result) => {
// 手动触发变更检测以更新 UI
this.ngZone.run(() => this.data = result);
};
});

回到Angular Zone

如果在runOutsideAngular中执行的代码需要更新Angular的UI,可以在需要的时候手动调用ngZone.run方法,把这些代码放回Angular的Zone中,这样就可以触发变更检测了。

这个过程相当于先跳出Angular的Zone,做一些不需要变更检测的操作,然后再手动回到Angular的Zone,触发变更检测。

1
2
3
4
5
6
ngZone.runOutsideAngular(() => {
// 长时间运行的计算任务
const result = longRunningTask();
// 手动触发变更检测以更新 UI
this.ngZone.run(() => this.data = result);
});