How to listen for mousemove event on Document object in Angular

前端 未结 1 1367
伪装坚强ぢ
伪装坚强ぢ 2020-12-02 17:15

I am implementing dragging functionality into an angular app: http://jsfiddle.net/Jjgmz/1/

Part of it, is to listen for mousemove event on a document ob

相关标签:
1条回答
  • 2020-12-02 17:48

    1) Using @HostListener (docs). This is the prefered method which should be enough most of the time.

    import {Component, NgModule, HostListener} from '@angular/core'
    
    @Component({
      ...
    })
    export class MyComponent {
      @HostListener('document:mousemove', ['$event']) 
      onMouseMove(e) {
        console.log(e);
      }
      ..
    }
    

    2) Similar to the above, you can also use (document:event)="handler" on any DOM element, but the above solution is prefered because the code is cleaner. By using this, it's not immediately obvious from the class that you have a global event listener, and you might add additional ones unnecessarily.

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

    3) The Renderer (docs) is a lower-level solution; useful when you do not want to clutter your code with methods, but deal with the even elsewhere, for example in a hook, as the following snippet shows. Be careful, though, as you still need to remove the event listener to prevent memory leaks; either do this when you know you won't need it anymore, or in the OnDestroy hook.

    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();
      }
    }
    

    4) Alternative of the first example is a host property, which is discouraged by the Angular Style Guide, since you now keep track of the function name in two places which can be very far apart physically in code. Prefer the first version whenever possible.

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

    5) A reactive way, which Angular embraces, is using Observable.fromEvent. This gives you a benefit of all RxJS operators for transforming the stream before executing a function. Be careful, though, as you need to unsubscribe manually to avoid memory leaks (unless you subscribe directly in the template using async pipe; this will handle unsubscription for you). Also don't forget to add-import the operator, as shown in the following snippet.

    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();
      }
    }
    

    6) Of course, document.addEventListener is always a solution as well; but this is not an intended usage in Angular apps; you should choose different ways. Directly accessing DOM is discouraged as it breaks Angular's neat encapsulation of DOM manipulation. Also you could run into problems with Universal and SSR.

    0 讨论(0)
提交回复
热议问题