1

I've three pages home, about & details and I added a keydown event listener on Vue mounted lifecycle hook for each page, so whenever user clicks ctrl + rightArrow I'm triggering nextPage() method, which will push the next page to vue router, similarly ctrl + leftArrow should trigger the prevPage(). I'm implementing the same functionality on each page with different routes in nextPage() & prevPage(). Here the problem is, even though I didn't add the keydown listener on some of the pages, the event is triggering and navigating to the routes from the previously loaded event listener also the previous listeners are triggering multiple times.

export default {
  mounted() {
    window.addEventListener('keydown', this.handleKeyPress);
  },
  methods: {
    handleKeyPress(e) {
      if (e.ctrlKey && e.keyCode === 37) { // Previous page
        this.prevPage();
      } else if (e.ctrlKey && e.keyCode === 39) { // Next page
        this.nextPage();
      }
    },
    nextPage() {
      this.$router.push({ name: 'about' });
    },
    prevPage() {
      this.$router.push({ name: 'home' });
    }
  }
}
Teja D
  • 133
  • 2
  • 8

2 Answers2

2

You can attach your event handler to document

created() {
    if (typeof window !== 'undefined') {
        document.addEventListener('keydown', this.handleKeyPress)
    }
},
beforeDestroy() {
    if (typeof window !== 'undefined') {
        document.removeEventListener('keydown', this.handleKeyPress)
    }
}
Naresh
  • 862
  • 3
  • 12
  • 35
1

You're binding the keydown event to the window and since you have a single-page app, the listener will still be listening for events on the window even if you go to another route (because the new route is in the same window). You could try using Vue's built-in event handling functionality to instead bind the keydown event to the root elements of each of your components like this. That way, when you go to a new route, a new listener would listen on the new components.

This is how you could bind an event to a div root element:

<template>
  <div v-on:keydown="handleKeyPress">
    <rest of your component's template>
  </div>
</template> 

You might need to also add the tabindex="0" attribute to the div root element in order for it to be able to listen for keyboard events.

tony19
  • 125,647
  • 18
  • 229
  • 307
D Malan
  • 10,272
  • 3
  • 25
  • 50
  • it works, but I need to listen for the whole `window`, not for a particular `div` – Teja D Apr 18 '19 at 15:54
  • Add and remove event listeners on the window in Vue router's [navigation guards](https://router.vuejs.org/guide/advanced/navigation-guards.html) then. – D Malan Apr 18 '19 at 18:42