Detect Back Button in Navigation Guards of Vue-Router Detect Back Button in Navigation Guards of Vue-Router vue.js vue.js

Detect Back Button in Navigation Guards of Vue-Router


This is the only way that I've found:

We can listen for popstate, save it in a variable, and then check that variable

// This listener will execute before router.beforeEach only if registered// before vue-router is registered with Vue.use(VueRouter)window.popStateDetected = falsewindow.addEventListener('popstate', () => {  window.popStateDetected = true})router.beforeEach((to, from, next) => {  const IsItABackButton = window.popStateDetected  window.popStateDetected = false  if (IsItABackButton && from.meta.someLogica) {    next(false)     return ''  }  next()})


As stated by @Yuci, all the router hook callbacks are performed before popstate is updated (and therefore not helpful for this use case)

What you can do:

methods: {    navigate(location) {        this.internalNavigation = true;        this.$router.push(location, function () {            this.internalNavigation = false;        }.bind(this));    }}
  1. Wrap 'router.push' with you own 'navigate' function
  2. Before calling router.push, set 'internalNavigation' flag to true
  3. Use vue router 'oncomplete' callback to set internalNavigation flag back to false

Now you can check the flag from within beforeEach callback and handle it accordingly.

router.beforeEach((to, from, next) => {  if ( this.internalNavigation ) {      //Do your stufff  }  next()})


Slight improvement to @yair-levy answer.

Wrapping push to own navigate method is not convenient because you usually want to call push() from various places. Instead, router original methods can be patched in one place without changes in remaining code.

Following code is my Nuxt plugin to prevent navigation triggered by back/forward buttons (used in Electron app to avoid back caused by mouse additional "back" button, which makes mess in Electron app)Same principle can be used for vanilla Vue and to track common back button together with your custom handling.

export default ({ app }, inject) => {  // this is Nuxt stuff, in vanilla Vue use just your router intances   const { router } = app  let programmatic = false  ;(['push', 'replace', 'go', 'back', 'forward']).forEach(methodName => {    const method = router[methodName]    router[methodName] = (...args) => {      programmatic = true      method.apply(router, args)    }  })  router.beforeEach((to, from, next) => {    // name is null for initial load or page reload    if (from.name === null || programmatic) {      // triggered bu router.push/go/... call      // route as usual      next()    } else {      // triggered by user back/forward       // do not route      next(false)    }    programmatic = false // clear flag  })}