【问题标题】:Prevent MouseEvent on Angular directive from triggering change detection防止 Angular 指令上的 MouseEvent 触发更改检测
【发布时间】:2022-08-08 21:52:01
【问题描述】:

我正在开发一个 Angular 项目,其中指令需要对 mouseenter 和 mouseleave 事件做出反应。它需要更新使用它的宿主元素的 CSS。

考虑下面的人为示例:

import { Directive, ElementRef, HostListener } from \'@angular/core\';

@Directive({
  selector: \'[appMouseEvents]\',
})
export class MouseEventsDirective {
  constructor(private element: ElementRef) {

  }
  @HostListener(\'mouseEnter\', [\'$event\'])
  onMouseEnter() {
    console.log(\'mouseenter\');
  }

  @HostListener(\'mouseleave\',[\'$event\'])
  onMouseLeave() {
    console.log(\'mouseleave\');
  }

}

app.component.html

<hello name=\"{{ name }}\"></hello>
<p appMouseEvents>
  Hover Mouse over me
</p>

当我在 Angular 开发工具中分析应用程序时,我看到这些事件导致 Angular 触发更改检测,这是不需要的,因为只有宿主元素的 CSS 受到影响。

有没有办法对指令中的鼠标事件做出反应而不触发更改检测?

这是一个演示应用程序: https://stackblitz.com/edit/angular-ivy-r6ln5w?file=src%2Fapp%2Fapp.component.ts

  • 等等为什么不使用:hover 伪类来处理这种情况?

标签: angular angular-changedetection


【解决方案1】:

是的,在 DOM 上触发的事件将由 zone.js 进行猴子修补,并触发更改检测。

我建议您使用本机浏览器功能来这里。就像在宿主元素上使用 :hover 伪 CSS 类一样。

:host:hover {
    // CSS rules
}

修复它的替代方法是使用 this.zone.runOutsideAngular 作为其他建议的答案。

【讨论】:

    【解决方案2】:

    您可能需要使用 NgZone 在 Angular 区域(范围)之外运行代码,从而防止角度变化检测https://angular.io/api/core/NgZone

    您的指令将如下所示:

        import { Directive, ElementRef, HostListener, NgZone } from '@angular/core';
    
    @Directive({
      selector: '[appMouseEvents]',
    })
    export class MouseEventsDirective {
      constructor(private element: ElementRef, private zone: NgZone) {
        this.zone.runOutsideAngular(() => {
          this.element.nativeElement.addEventListener('mouseenter', (e) => {
            // e.preventDefault();
            // e.stopPropagation();
            console.log('mouseenter');
          });
        });
    
        this.zone.runOutsideAngular(() => {
          this.element.nativeElement.addEventListener('mouseleave', (e) => {
            // e.preventDefault();
            // e.stopPropagation();
            console.log('mouseleave');
          });
        });
      }
    }

    这是你的stackblitz修改https://stackblitz.com/edit/angular-ivy-faavr3?file=src/app/mouse-events.directive.ts

    希望这可以帮助。

    编辑:更新的源代码

    https://stackblitz.com/edit/angular-ivy-qvyk2t?file=src%2Fapp%2Fmouse-events.directive.ts

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多