Search code examples
vue.jsvuejs2addeventlistenervue-class-componentsremoveeventlistener

Vue class component AddEventListener and RemoveEventListener usage


I want to implement draggable line using mousedown, mousemove and mouseup events.

In my first attempt I was trying to use arrow-functions-class-properties: https://codesandbox.io/s/example-1-15psm?fontsize=14&hidenavigation=1&theme=dark

But the property position in Test.vue seems to be non-reactive. Not sure, but my guess is it's because of this Vue restriction:

Don’t use arrow functions on an options property or callback, such as created: () => console.log(this.a) or vm.$watch('a', newValue => this.myMethod()). Since an arrow function doesn’t have a this, this will be treated as any other variable and lexically looked up through parent scopes until found, often resulting in errors such as Uncaught TypeError: Cannot read property of undefined or Uncaught TypeError: this.myMethod is not a function.

In my second attempt I've tryed to use standart class methods: https://codesandbox.io/s/example-2-t7beu?fontsize=14&hidenavigation=1&theme=dark

It works, except since binded functions onMouseMove and onMouseUp in Test.vue are anonymous I can't unbind them with removeEventListener.

So, what's the proper way of using addEventListener and removeEventListener in Vue class components?


Solution

  • I've overengineered my code. There is no need to use arrow-functions-class-properties, or defining context by using method.bind(this). The following code should work:

    import { Vue, Component } from "vue-property-decorator";
    
    @Component
    export default class Test extends Vue {
      position = 0;
    
      onMouseMove(e) {
        let position = this.position;
        position += e.movementY;
        this.position = position;
        console.log("onMouseMove", this.position);
      }
    
      onMouseUp() {
        console.log("onMouseUp", this.position);
        document.removeEventListener("mousemove", this.onMouseMove);
        document.removeEventListener("mouseup", this.onMouseUp);
      }
    
      onMouseDown() {
        console.log("onMouseDown", this.position);
        document.addEventListener("mousemove", this.onMouseMove);
        document.addEventListener("mouseup", this.onMouseUp);
      }
    }
    
    

    Working example: https://codesandbox.io/s/example-2-t7beu?fontsize=14&hidenavigation=1&theme=dark