检测Vue-Router导航护罩中的后退按钮

Asq*_*qan 1 javascript cordova vue.js vue-router vuejs2

路线的更改方式对我来说很重要。因此,我想抓住浏览器或gsm的后退按钮更改路线的时间。

这就是我所拥有的:

router.beforeEach((to, from, next) => {
  if ( /* IsItABackButton && */ from.meta.someLogica) {
    next(false) 
    return ''
  }
  next()
})
Run Code Online (Sandbox Code Playgroud)

有没有一些我可以代替IsItABackButton注释使用的内置解决方案?我猜Vue-router本身还没有,但是任何解决方法也可以在这里工作。还是会有另一种首选的方式来识别它?

far*_*ncz 7

对@yair-levy 答案略有改进。

包装push到自己的navigate方法并不方便,因为您通常想要push从不同的地方调用 () 。相反,路由器原始方法可以在一处进行修补,而无需更改其余代码。

以下代码是我的 Nuxt 插件,用于防止后退/前进按钮触发导航(在 Electron 应用程序中使用,以避免由鼠标附加“后退”按钮引起的后退,这会使 Electron 应用程序变得混乱)相同的原理可用于 vanilla Vue 并跟踪通用后退按钮以及您的自定义处理。

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
  })
}
Run Code Online (Sandbox Code Playgroud)


Nun*_*rez 6

这是我发现的唯一方法:

我们可以监听popstate,将其保存在变量中,然后检查该变量

// This listener will execute before router.beforeEach only if registered
// before vue-router is registered with Vue.use(VueRouter)

window.popStateDetected = false
window.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()
})
Run Code Online (Sandbox Code Playgroud)

  • @Nuno Balbona Pérez,看起来 popstate 事件处理程序在 router.beforeEach 回调*之后*运行。我认为这不会像现在这样有效。 (5认同)

Yai*_*evy 5

正如 @Yuci 所说,所有路由器钩子回调都是在更新 popstate之前执行的(因此对此用例没有帮助)

你可以做什么:

methods: {
    navigate(location) {
        this.internalNavigation = true;
        this.$router.push(location, function () {
            this.internalNavigation = false;
        }.bind(this));
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 用您自己的“导航”功能包装“router.push”
  2. 在调用 router.push 之前,将 'internalNavigation' 标志设置为 true
  3. 使用 vue router 'oncomplete' 回调将internalNavigation 标志设置回 false

现在您可以在 beforeEach 回调中检查该标志并进行相应的处理。

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


小智 5

在花了很多时间尝试改进代码以使其在我的情况下运行良好且没有故障之后,我找到了一种简单的方法来解决这个问题。

export const handleBackButton = () => {
    router.beforeEach((to, from, next) => {
        if (window.event.type == 'popstate' && from.name == 'HomePage'){  
            next(false);
        }else{  
            next(); 
        }
    });
}
Run Code Online (Sandbox Code Playgroud)
  • 检查window.event.type == 'popstate'后退按钮是否被按下
  • from.name == 'HomePage'检查按下后退按钮的页面或您正在路由的页面。
  • HomePage 作为您要禁用后退按钮的名称。如果您想在整个站点中禁用它,您可以保留此条件。
  • next(false) and next()分别停止或允许导航。
  • 您可以将代码放在 navigationGuard.js 文件中并将其导入到 main.js 文件中
  • 我尝试了其他方法,包括从组件调用,但它会产生故障并且重新路由变得明显。但这根本不会留下任何故障。

希望这对你有用。干杯