组件内Navigation Guard回调无效:Nuxt JS和`beforeRouteEnter`

时间:2019-10-22 03:37:24

标签: javascript vue.js vuejs2 vue-router nuxt.js

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

我正在尝试使用组件内防护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

:facepalm:

1 个答案:

答案 0 :(得分: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路由器一样具有相同的行为 官方文档:Clumsy