[Angular] USING ZONES IN ANGULAR FOR BETTER PERFORMANCE

Link to the artical.

 

Zone detects any async opreations. Once an async oprations happens in Angular, Zone will notify change detection to kick in.

 

Images we have 5000 svg box displaying on the screen.

And each svg elements and three event listener on it:

复制代码
@Component({
  ...
  template: `
    <svg (mousedown)="mouseDown($event)"
         (mouseup)="mouseUp($event)"
         (mousemove)="mouseMove($event)">

      <svg:g box *ngFor="let box of boxes" [box]="box">
      </svg:g>

    </svg>
  `
})
class AppComponent {
  ...
}
复制代码

Three (3) event handlers are bound to the outer SVG element. When any of these events fire and their handlers have been executed then change detection is performed. In fact, this means that Angular will run change detection, even when we just move the mouse over the boxes without actually dragging a single box!

 

Since 'mousemove' is the event cause the change detection which is not necessary. So we simple remove it from the HTML:

<svg (mousedown)="mouseDown($event)"
      (mouseup)="mouseUp($event)">

  <svg:g box *ngFor="let box of boxes" [box]="box">
  </svg:g>

</svg>

 

So now we need a way to attach 'mousemove' event for only the selected svg box. We can do this inside 'mousedown' event:

复制代码
  constructor(private zone: NgZone) {}

  mouseDown(event) {
    ...
    this.element = event.target;

    this.zone.runOutsideAngular(() => {
      window.document.addEventListener('mousemove', this.mouseMove.bind(this));
    });
  }
复制代码

We inject NgZone and call runOutsideAngular() inside our mouseDown() event handler, in which we attach an event handler for the mousemove event. This ensures that the mousemove event handler is really only attached to the document when a box is being selected.

 

  mouseMove(event) {
    event.preventDefault();
    this.element.setAttribute('x', event.clientX + this.clientX + 'px');
    this.element.setAttribute('y', event.clientX + this.clientY + 'px');
  }

In addition, we save a reference to the underlying DOM element of the clicked box so we can update its x and y attributes in the mouseMove() method. We’re working with the DOM element instead of a box object with bindings for x and y, because bindings won’t be change detected since we’re running the code outside Angular’s Zone. In other words, we do update the DOM, so we can see the box is moving, but we aren’t actually updating the box model (yet).

 

In the next step, we want to make sure that, whenever we release a box (mouseUp), we update the box model, plus, we want to perform change detection so that the model is in sync with the view again. The cool thing about NgZone is not only that it allows us to run code outside Angular’s Zone, it also comes with APIs to run code inside the Angular Zone, which ultimately will cause Angular to perform change detection again. All we have to do is to call NgZone.run() and give it the code that should be executed.

Here’s the our updated mouseUp() event handler:

复制代码
@Component(...)
export class AppComponent {
  ...
  mouseUp(event) {
    // Run this code inside Angular's Zone and perform change detection
    this.zone.run(() => {
      this.updateBox(this.currentId, event.clientX + this.offsetX, event.clientY + this.offsetY);
      this.currentId = null;
    });

    window.document.removeEventListener('mousemove', this.mouseMove);
  }
}
复制代码

Also notice that we’re removing the event listener for the mousemove event on every mouseUp. Otherwise, the event handler would still be executed on every mouse move. In other words, the box would keep moving even after the finger was lifted, essentially taking the drop part out of drag and drop. In addition to that, we would pile up event handlers, which could not only cause weird side effects but also blows up our runtime memory.

 

Notice:

However, we shouldn’t forget that this solution also comes with a couple (probably fixable) downsides. For example, we’re relying on DOM APIs and the global window object, which is something we should always try to avoid. If we wanted to use this code with on the server-side then direct access of the window variable would be problematic. We will discus these server-side specific issues in a future article. For the sake of this demo, this isn’t a big deal though.

posted @   Zhentiw  阅读(444)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2016-03-17 [AngularJS] Angular 1.5 multiple transclude
2016-03-17 [RxJS] Creating Observable From Scratch
2015-03-17 [AngularJS] Introduction to angular-formly
点击右上角即可分享
微信分享提示