如何在Angular中的Document对象上侦听mousemove事件

san*_*han 21 angular

我正在将拖动功能实现为一个角度应用程序:http://jsfiddle.net/Jjgmz/1/

部分原因是监听mousemove文档对象上的事件.

$(document).mousemove(function(e) {});
Run Code Online (Sandbox Code Playgroud)

如何在组件内部监听文档对象?

让我们假装这是component.html文件的内容:

<div id="box"></div>
Run Code Online (Sandbox Code Playgroud)

我正在使用Angular 4.

yur*_*zui 75

1)使用@HostListener(docs).这是首选的方法,大多数时候应该足够了.

import {Component, NgModule, HostListener} from '@angular/core'

@Component({
  ...
})
export class MyComponent {
  @HostListener('document:mousemove', ['$event']) 
  onMouseMove(e) {
    console.log(e);
  }
  ..
}
Run Code Online (Sandbox Code Playgroud)

2)与上面类似,你也可以使用(document:event)="handler"任何DOM元素,但上面的解决方案是首选的,因为代码更清晰.通过使用它,从类中可以立即看出您有一个全局事件侦听器,并且您可能不必要地添加其他事件.

@Component({
  selector: 'my-app',
  template: `
    <div (document:mousemove)="onMouseMove($event)" id="box"></div>
  `,
})
export class MyComponent {
  onMouseMove(e) {
    console.log(e);
  }
}
Run Code Online (Sandbox Code Playgroud)

3)Renderer(docs)是一个较低级别的解决方案; 当您不希望使用方法混乱代码时有用,但是在其他地方处理它们,例如在钩子中,如下面的代码段所示.但是要小心,因为您仍然需要删除事件侦听器以防止内存泄漏; 当你知道你不再需要它时,或者在OnDestroy钩子中,要么这样做.

import { Component, Renderer2 } from '@angular/core';

@Component({
  ...
})
export class MyComponent {
  globalListenFunc: Function;

  constructor(private renderer: Renderer2) {}

  ngOnInit() {
    this.globalListenFunc = this.renderer.listen('document', 'mousemove', e => {
      console.log(e);
    });
  }

  ngOnDestroy() {
    // remove listener
    this.globalListenFunc();
  }
}
Run Code Online (Sandbox Code Playgroud)

4)第一个例子的替代方案是一个主机属性,它不受Angular Style Guide的阻止,因为你现在可以在两个地方跟踪功能名称,这两个地方的代码可能相差很远.尽可能优先考虑第一个版本.

@Component({
  ...
  host: {
    '(document:mousemove)': 'onMouseMove($event)'
  }
})
export class MyComponent {
  onMouseMove(e) {
    console.log(e);
  }
}
Run Code Online (Sandbox Code Playgroud)

5)Angular所采用的反应方式Observable.fromEvent.这为您提供了在执行函数之前转换流的所有RxJS运算符的好处.但要小心,因为您需要手动取消订阅以避免内存泄漏(除非您使用async管道直接在模板中订阅;这将为您处理取消订阅).另外,不要忘记添加 - 导入运算符,如下面的代码段所示.

import { Subscription, fromEvent } from 'rxjs';

@Component({
  ...
})
export class MyComponent {
  subscription: Subscription;

  ngOnInit() {
    this.subscription = 
         fromEvent(document, 'mousemove')
                           .subscribe(e => {
                             console.log(e);
                           });
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}
Run Code Online (Sandbox Code Playgroud)

6)当然,document.addEventListener总是一个解决方案; 但这不是Angular应用程序中的预期用途; 你应该选择不同的方式.不鼓励直接访问DOM,因为它打破了Angular对DOM操作的整洁封装.你也可能遇到Universal和SSR的问题.

  • 你应该写一本书。 (4认同)
  • 请注意解决方案 1,因为它会在每次捕获事件时触发整个应用程序的 changeDetector,而不是我认为您想要的。 (2认同)
  • 如何在特定元素(而不是文档)上监听此事件? (2认同)