9

在我一直使用的组件中:

this.$router.push({ name: 'home', params: { id: this.searchText }});

改变路线。我现在已经将一个方法移动到我的 Vuex 操作中,当然this.$router不再有效。也没有Vue.router。那么,请问如何从 Vuex 状态调用路由器方法?

4

5 回答 5

15

我假设vuex-router-sync在这里没有帮助,因为您需要路由器实例。

因此,虽然这感觉不太理想,但您可以在 webpack 中将实例设置为全局,即

global.router = new VueRouter({
  routes
})

const app = new Vue({
  router
  ...

现在您应该能够:router.push({ name: 'home', params: { id: 1234 }})从您的应用程序中的任何位置


作为替代方案,如果您不喜欢上述想法,您可以从您的操作中返回一个 Promise。然后,如果操作成功完成,我假设它会调用突变或其他东西,您可以resolve使用 Promise。但是,如果它失败并且重定向需要的任何条件都会命中你reject的承诺。

这样,您可以将路由器重定向移动到一个组件中,该组件仅捕获被拒绝的 Promise 并触发 vue-router 推送,即

# vuex
actions: {
  foo: ({ commit }, payload) =>
    new Promise((resolve, reject) => {
      if (payload.title) {
        commit('updateTitle', payload.title)
        resolve()
      } else {
        reject()
      }
    })

# component
methods: {
  updateFoo () {
    this.$store.dispatch('foo', {})
      .then(response => { // success })
      .catch(response => {
        // fail
        this.$router.push({ name: 'home', params: { id: 1234 }})
      })
于 2016-11-23T15:52:46.253 回答
1

我的情况,我发现自己使用.go而不是.push.

抱歉,没有解释为什么,但在我的情况下它有效。我把它留给像我这样的未来谷歌人。

于 2019-05-06T13:24:41.747 回答
0
    state: {
        anyObj: {}, // Just filler
        _router: null // place holder for router ref
    },
    mutations: {
        /***
        * All stores that have this mutation will run it
        *
        *  You can call this in App mount, eg...

        *  mounted () {
        *    let vm = this
        *    vm.$store.commit('setRouter', vm.$router)
        *  }
        *
        setRouter (state, routerRef) {
            state._router = routerRef
        }
    },
    actions: {
        /***
        * You can then use the router like this
        * ---
        someAction ({ state }) {
            if (state._router) {
                state._router.push('/somewhere_else')
            } else {
                console.log('You forgot to set the router silly')
            }
        }
    }
}

于 2019-06-18T12:13:33.097 回答
0

假设您在主 Vue 构造函数中作为选项传递,我相信rootState.router您的操作将可用。router

正如 GuyC 所提到的,我还认为你最好从你的行动中返回一个承诺并在它解决后路由。简单来说:dispatch(YOUR_ACTION).then(router.push()).

于 2016-11-24T04:12:27.403 回答
0

更新

在我发布这个答案后,我注意到以我呈现 Typescript 的方式定义它停止检测state. 我认为那是因为我用作any类型。我可能可以手动定义类型,但这听起来像是在重复我自己。就目前而言,我最终得到了一个函数而不是扩展一个类(如果有人知道,我很高兴让我知道其他解决方案)。

import { Store } from 'vuex'
import VueRouter from 'vue-router'
// ...

export default (router: VueRouter) => {
  return new Store({
  // router = Vue.observable(router) // You can either do that...
  super({
    state: {
      // router // ... or add `router` to `store` if You need it to be reactive.
      // ...
    },
    // ...
  })
}
import Vue from 'vue'
import App from './App.vue'
import createStore from './store'
// ...

new Vue({
  router,
  store: createStore(router),
  render: createElement => createElement(App)
}).$mount('#app')

初步回答内容

Store我个人只是为一个典型的类做了一个包装器。

import { Store } from 'vuex'
import VueRouter from 'vue-router'
// ...

export default class extends Store<any> {
  constructor (router: VueRouter) {
    // router = Vue.observable(router) // You can either do that...
    super({
      state: {
        // router // ... or add `router` to `store` if You need it to be reactive.
        // ...
      },
      // ...
    })
  }
}

如果您需要$route,您可以使用router.currentRoute. 请记住,如果您希望 Your with按预期工作,您宁愿需要router响应式。gettersrouter.currentRoute

在“main.ts”(或“.js”)中,我只是将它与new Store(router).

import Vue from 'vue'
import App from './App.vue'
import Store from './store'
// ...

new Vue({
  router,
  store: new Store(router),
  render: createElement => createElement(App)
}).$mount('#app')
于 2020-11-15T20:40:41.983 回答