组件内导航防护回调不起作用:Nuxt JS 和`beforeRouteEnter`

Posted

技术标签:

【中文标题】组件内导航防护回调不起作用:Nuxt JS 和`beforeRouteEnter`【英文标题】:In-component Navigation Guard callback not working: Nuxt JS and `beforeRouteEnter` 【发布时间】:2020-02-18 03:49:57 【问题描述】:

我有一个使用 Nuxt JS 构建的搜索表单和结果页面。如果表单返回错误,我正在尝试将结果页面 pages/results/index.vue 重定向回搜索页面 pages/search/index.vue

我正在尝试使用 In-Component Guards per the Vue documentation

根据文档:

但是,您可以通过将回调传递给 next 来访问该实例。导航确认后会调用回调,并将组件实例作为参数传递给回调:

beforeRouteEnter (to, from, next) 
  next(vm => 
    // access to component instance via `vm`
  )

// version info

├─┬ nuxt@2.10.1
│ ├─┬ @nuxt/builder@2.10.1
│ │ └─┬ @nuxt/vue-app@2.10.1
│ │   └── vue@2.6.10  deduped
│ └─┬ @nuxt/core@2.10.1
│   └─┬ @nuxt/vue-renderer@2.10.1
│     └── vue@2.6.10  deduped
└─┬ vue-glide-js@1.3.12
  └── vue@2.6.10

我的主要问题是导航守卫中 next() 函数中的回调似乎无法重新路由页面。

来自页面)

// page/search/index.vue

<template>
  ...
  <nuxt-link to="/results" @click.native="doSearch">
    Show Results
  </nuxt-link>
  ...
</template>

<script>
export default 
  ...
  methods: 
    doSearch () 
      ... // validates search fields and adds content to store
    
  ,
  ...

</script>

上述工作正常,doSearch 验证表单并将结果(以及任何错误)添加到商店。

但是接下来...

页面)

// pages/results/index.vue

<script>
export default 
  ...
  beforeRouteEnter (to, from, next) 
    next((vm) => 
      console.log(vm.validateRoute()) // works: '/search'
      vm.validateRoute()              // does not work: does nothing
    )
  ,
  ...
  computed: 
    errors () 
      return this.$store.state.errors
    
  ,
  ...
  async fetch ( store, params ) 
    await store.dispatch('searchresults/GET_RESULTS')
  ,
  ...
  methods: 
    validateRoute () 
      let route = true
      if (this.errors.length > 0) 
        route = '/search'
      
      console.log(this.erros.length)  // works: 7
      console.log(route)              // works: '/search'
      return route
    
  ,
  ...

</script>

beforeRouteEnter 中的回调似乎没有被评估并且不会导致路由更改。请注意,日志显示回调正在触发并返回正确的值。

如果我明确定义路由,而不使用回调函数,它可以工作:

// pages/results/index.vue

<script>
export default 
  ...
  beforeRouteEnter (to, from, next) 
    next('/search')                   // works: re-routes to '/search' every time
  ,
  ...

</script>

我尝试了几次next(callback) 的迭代,但效果有限...

next(() =>  return false )          // does not work
next(function ()  return false )    // does not work

但只有显式声明才有效...

next( path: false )                 // works: prevents route change
next( path: '/search' )             // works: changes route to '/search'

我完全不知所措;这是一个错误,还是我错过了什么?

附录

我之前尝试过使用Nuxt documentation here 中提到的中间件。然而,这导致了无限循环,正如this blog post 中所讨论的那样。

// middleware/validate.js

export default function ( store, redirect ) 
  console.log('middleware: validate')           // 'middleware: validate'
  if (store.state.errors.length > 0) 
    return redirect('/search')                  // ...endless loop
  
  return true                                   // otherwise this works


// nuxt.config.js

export default 
  ...
  router: 
    middleware: "validate"
  ,
  ...

已修复

正如@ifaruki 所指出的,将中间件调用放在页面组件中可以解决死循环问题:

下一步是将中间件添加到页面 pages/results/index.vue 中,如下所示:

export default 
   middleware: 'validate'
 

我在the docs 的最后发现了这个,这似乎是Vue JS In-component Guards 的 Nuxt 方法:

您也可以将中间件添加到特定布局或页面:

pages/index.vuelayouts/default.vue

:脸:

【问题讨论】:

你试过用return vm.validateRoute()代替vm.validateRoute()吗?我的意思是在回调内部next((vm) =&gt; // Here ) 【参考方案1】:

对于这种情况,nuxt.js 有一个名为 middleware 的属性。

您可以使用middleware 代替守卫。在您的中间件文件夹中,您首先创建一个名为 validate.js 的文件。

在您的 validate.js 文件中,您创建一个函数并将您的验证逻辑放入其中:

export default function ( store, redirect ) 
  if (store.state.errors.length > 0) 
    return redirect('/search')
  

现在您已经设置了中间件。下一步是将中间件添加到您的页面pages/results/index.vue,如下所示:

export default 
   middleware: 'validate'
 

中间件总是在创建 vue 实例之前被调用。每当 store.state.errors 大于 0 时,您将被重定向回 /search 否则此中间件将被忽略。

始终首先阅读 nuxt 文档,因为 nuxt 并不总是具有与 vue.js 或 vue.js 路由器相同的行为 官方文档:https://nuxtjs.org/api/pages-middleware

【讨论】:

感谢@ifaruki - 我最初错过了 Nuxt 文档中关于将中间件直接添加到页面组件的部分。全局添加会导致无休止的重定向循环。我应该提到我已经查看了 Nuxt 文档和无限循环结果,并相应地更新了问题。 我还想在这里补充一点,redirect(false) 不起作用,但 redirect( path: false ) 起作用。

以上是关于组件内导航防护回调不起作用:Nuxt JS 和`beforeRouteEnter`的主要内容,如果未能解决你的问题,请参考以下文章

导航组件在 onActivityResult 内导航不起作用

组件动态导入在 router.js 中不起作用

nuxt 类组件。异步获取不起作用

了解 Nuxt.js 中的状态和吸气剂:吸气剂不起作用

如何使用 Nuxt.js 从缓存中排除组件?

Nuxt:在 Vue 页面组件中包含 3rd 方库