web-dev-qa-db-fra.com

Comment naviguer à l'aide de vue router à partir d'actions Vuex

Je crée une application Web avec Vue 2.x et Vuex 2.x. Je vais chercher des informations à distance via un appel http, je veux que si cet appel échoue, je devrais rediriger vers une autre page.

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

Mais this.$router.Push({path:"/"}) me donne l'erreur suivante.

Non capturé (promis) TypeError: Impossible de lire la propriété 'Push' of indéfinie

Comment cela peut il etre accompli.

JsFiddle simulé: ici

35
Saurabh

import router from './router'

et utilisez router.Push

Aussi simple que ça.

67
M U

Il semble que vous n'injectiez pas votre routeur dans votre application, ce qui explique son indétermination.

Dans les versions précédentes de vue-router, vous devriez: Vue.use(VueRouter), avec la version 2.0, vous pouvez injecter le routeur dans l'application comme ci-dessous:

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

const router = new VueRouter({
  routes
})

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

cela devrait alors le rendre disponible en tant que this.$router dans toute l'application


Après avoir répondu à une question connexe: Comment utiliser Vue Router à partir de l’état Vuex? il semble que Vuex ne reçoive pas l'instance de routeur à this.$router. Par conséquent, deux méthodes ont été suggérées pour fournir un accès à l'instance de routeur. 

La première est plus directe, ce qui implique de définir un pack Web global pour l'instance.

La seconde consiste à utiliser Promises avec votre action vuex pour permettre à vos composants d’utiliser leur référence à l’instance de routeur après les actions de résolution/rejet de Promise.

8
GuyC

Cet exemple peut vous aider.

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");
} 
7
bocai

Je n'aimais pas que l'état de l'emplacement de mon application soit séparé du reste de l'état de celui-ci dans la boutique et qu'il faille gérer à la fois un routeur et un magasin. J'ai donc créé un module Vuex qui gère l'état de localisation dans le Le magasin. 

Maintenant, je peux naviguer en distribuant des actions, comme tout autre changement d'état:

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

Cela présente l'avantage supplémentaire de faciliter la gestion d'éléments tels que les transitions de page animées.

Ce n'est pas difficile de lancer votre propre module router, mais vous pouvez aussi essayer le mien si vous voulez:

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

4
Chris Jaynes

Dans main.js (celui dans lequel nous "installons" tous les modules et créons une instance Vue, c'est-à-dire src/main.js):

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

export { vm }

Ceci est mon exemple, mais dans notre cas, le plus important ici est const vm et router

Dans votre store:

import { vm } from '@/main'

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

P.S. En utilisant import { vm } from '@/main', nous pouvons accéder à tout ce dont nous avons besoin dans Vuex, par exemple vm.$root, nécessaire à certains composants de bootstrap-vue.

P.P.S. Il semble que nous pouvons utiliser vm au moment même où tout est chargé. En d'autres termes, nous ne pouvons pas utiliser vm dans someMutation au cas où, si nous appelons someMutation dans mounted(), car mounted() arrive/se produit avant que vm soit créé.

1
TitanFighter