How to navigate using vue router from Vuex actions

回眸只為那壹抹淺笑 提交于 2019-11-26 16:48:36

问题


I am creating a web app with Vue 2.x and Vuex 2.x. I am fetching some information from a remote location via an http call, I want that if that call fails I should redirect to some other page.

GET_PETS: (state) => {
  return $http.get('pets/').then((response)=>{
      state.commit('SET_PETS', response.data)
    })
  },
  error => {this.$router.push({path:"/"}) }
  )
}

But this.$router.push({path:"/"}) gives me following error.

Uncaught (in promise) TypeError: Cannot read property 'push' of undefined

How can this be achieved.

Simulated JsFiddle: here


回答1:


import router from './router'

and use router.push

Simple like that.




回答2:


It looks like you aren't injecting your router into your app, hence it being 'undefined'

In previous versions of vue-router you would: Vue.use(VueRouter), with 2.0 you can inject the router into the app like below:

const routes = [
  { path: '/foo', component: Foo },
]

const router = new VueRouter({
  routes
})

const app = new Vue({
  router // inject the router
}).$mount('#app')

this should then make it available as this.$router throughout the app


Following answering a related question: How to use Vue Router from Vuex state? it seems that Vuex won't receive the router instance at this.$router. Therefore two methods were suggested to provide access to the router instance.

The first is more direct which involves setting a webpack global to the instance.

The second involves using Promises with your vuex action that would allow your components to utilise their reference to the router instance following the actions Promise resolving / rejecting.




回答3:


This example may help you.

main.js

import Vue from "vue";
import VueRouter from "vue-router";

...

Vue.use(VueRouter);

export const router = new VueRouter({
    mode: 'hash',
    base: "./",
    routes: [
        { path: "/", component: welcome},
        { path: "/welcome", component: welcome},

    ]
})

actions.js

import {router} from "../main.js"

export const someAction = ({commit}) => {

    router.push("/welcome");
} 



回答4:


I didn't like keeping my app's location state separate from the rest of my app state in the Store, and having to manage both a Router and a Store, so I created a Vuex module that manages the location state inside the Store.

Now I can navigate by dispatching actions, just like any other state change:

dispatch("router/push", {path: "/error"})

This has the added benefit of making things like animated page transitions easier to handle.

It's not hard to roll your own router module, but you can also try mine if you want to:

https://github.com/geekytime/vuex-router




回答5:


INITIAL ANSWER

In main.js (the one, where we "install" all modules and create Vue instance, i.e. src/main.js):

const vm = new Vue({
  el: '#app',
  router,
  store,
  apolloProvider,
  components: { App },
  template: '<App/>'
})

export { vm }

This is my example, but in our case the most important here is const vm and router

In your store:

import { vm } from '@/main'

yourMutation (state, someRouteName) {
  vm.$router.push({name: someRouteName})
}

P.S. Using import { vm } from '@/main' we can access anything we need in Vuex, for example vm.$root which is needed by some components of bootstrap-vue.

P.P.S. It seems we can use vm just when everything is loaded. In other words we can not use vm inside someMutation in case, if we call someMutation inside mounted(), because mounted() comes/occurs before vm is created.


NEW ANSWER

Constantin's answer (the accepted one) is better than mine, so just want to show for novice how to implement it.

Inside core dir (inside /src in my case), next to App.vue, main.js and others I have router.js with the content:

import Vue from 'vue'
import Router from 'vue-router'

// Traditional loading
import Home from '@/components/pages/Home/TheHome'

// Lazy loading (lazy-loaded when the route is visited)
const Page404 = () => import(/* webpackChunkName: "Page404" */ '@/components/pages/404)
const Page503 = () => import(/* webpackChunkName: "Page503" */ '@/components/pages/503)

Vue.use(Router)

const router = new Router({
  mode: 'hash',
  base: process.env.BASE_URL,
  linkExactActiveClass: 'active',
  routes: [
    {
      path: '*',
      name: 'Page404',
      component: Page404
    },

    {
      path: '*',
      name: 'Page503',
      component: Page503
    },

    {
      path: '/',
      name: 'Home',
      component: Home
    },

    // Other routes
    {....},
    {....}
  ]
})

// Global place, if you need do anything before you enter to a new route.
router.beforeEach(async (to, from, next) => {
  next()
})

export default router

Import our router to main.js:

import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = false

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

export { vm }

Finally, inside your component, or Vuex or anywhere else import router from './router' and do whatever you need, such as router.push(...)



来源:https://stackoverflow.com/questions/40736799/how-to-navigate-using-vue-router-from-vuex-actions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!