38

Vue.js allow apply event on element:

<div id="app">
   <button @click="play()">Play</button>
</div>

But how to apply event on window object? it is not in DOM.

for example:

<div id="app">
  <div @mousedown="startDrag()" @mousemove="move($event)">Drag me</div>
</div>

in this example, how to listen mousemove event on window ?

5 Answers 5

82

You should just do it manually during the creation and destruction of the component

...
created: function() {
  window.addEventListener('mousemove',this.move);
},
destroyed: function() {
  window.removeEventListener('mousemove', this.move);
}
...
2
  • Thanks Jeff. The answer was helpful. Do I need destroyed if I have to add the listener in the main parent component on App level?
    – user12009061
    Commented Feb 2, 2021 at 16:28
  • Destroying registered listener isn't required on the main component of your project unless it might be embedded in more complex setup with your vue application being just one part of the view. Thus, unregistering everything is best practice in all situations to make your code future proof. Commented Apr 8, 2022 at 10:25
17

Jeff's answer is perfect and should be the accepted answer. Helped me out a lot!

Although, I have something to add that caused me some headache. When defining the move method it's important to use the function() constructor and not use ES6 arrow function => if you want access to this on the child component. this doesn't get passed through to arrow functions from where it's called but rather referrers to its surroundings where it is defined. This is called lexical scope.

Here is my implementation with the called method (here called keyDown instead of move) included:

export default {
  name: 'app',
  components: {
    SudokuBoard
  },
  methods: {
    keyDown: function () {
      const activeElement = document.getElementsByClassName('active')[0]
      if (activeElement && !isNaN(event.key) && event.key > 0) {
        activeElement.innerHTML = event.key
      }
    }

  },

  created: function () {
    window.addEventListener('keydown', this.keyDown)
  },

  destroyed: function () {
    window.removeEventListener('keydown', this.keyDown)
  }
}

To be extra clear, The method below doesn't have access to this and can't for example reach the data or props object on your child component.

methods: { 
    keyDown: () => {
      //no 'this' passed. Can't access child's context 
      }
1
  • Your example isn't even using this in the keyDown() function. I doubt this is pointing to the component there anyways. If you actually need access to the component it is safest to bind the handler or use arrow function on registration. But in that case you have to save that bound/arrow function as a property of your component for use on removeEventListener() to prevent memory leak, too. Commented Apr 8, 2022 at 10:22
7

You can also use the vue-global-events library.

<GlobalEvents @mousemove="move"/>

It also supports event modifiers like @keydown.up.ctrl.prevent="handler".

4

This is for someone landed here searching solution for nuxt.js:

I was creating sticky header for one of my projects & faced issue to make window.addEventListener work.

First of all, not sure why but window.addEventListener doesn't work with created or beforeCreate hooks, hence I am using mounted.

<template lang="pug">
  header(:class="{ 'fixed-header': scrolled }")
    nav menu here
</template>

<script>
export default {
  name: 'AppHeader',

  data() {
    return { scrolled: false };
  },

  mounted() {
    // Note: do not add parentheses () for this.handleScroll
    window.addEventListener('scroll', this.handleScroll);
  },

  methods: {
    handleScroll() {
      this.scrolled = window.scrollY > 50;
    },
  },
};
</script>
1
  • mounted / unmounted should be always preferred over created / destroyed to support SSR. I guess, this applied in your case, too. Commented Apr 8, 2022 at 10:18
4

I found that using window.addEventListener no longer worked as I expected with Vue 3. It appears that the function is wrapped by Vue now. Here's a workaround:

...
created()
{
  document.addEventListener.call(window, "mousemove", event =>
  {
    ...
  });
}
...

The important part is document.addEventListener.call(window, what we're doing is to take the unwrapped addEventListener from document and then call it on the window Object.

1
  • This does not seem to work in the Vue 3 CDN version
    – Loosie94
    Commented Apr 6, 2023 at 11:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.