102 votes

Comment naviguer à l'aide de Vue Router à partir d'actions Vuex ?

Je suis en train de créer une application web avec Vue 2.x et Vuex 2.x. Je suis en train de récupérer des informations d'un emplacement distant via un appel http, je veux que si cet appel échoue je sois redirigé vers une autre page.

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

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

Erreur de type (dans la promesse) non attrapée : Impossible de lire la propriété 'push' d'undefined.

Comment y parvenir ?

JsFiddle simulé : aquí

0 votes

C'est parce que vous l'utilisez à l'intérieur d'une fonction flèche qui traite 'this' comme un littéral. convertissez-la en une fonction régulière ou utilisez les réponses suggérées ci-dessous...

230voto

M U Points 3634

import router from './router'

et utiliser router.push

C'est aussi simple que ça.

2 votes

Ne fonctionne pas sur quasar v2 Module non trouvé : Impossible de résoudre la dépendance importée " ./router ".

22voto

bocai Points 146

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

3 votes

Ce n'est pas ainsi que vous devez utiliser Vue. Les actions ne devraient pas avoir d'effets secondaires. Résolvez ce problème dans les méthodes du composant comme dispatch('someAction').then(() => this.$router.push('/welcome'))

5 votes

@adriaan pas strictement vrai, même les actions dans les démos vuex ont des effets secondaires.

6 votes

@adriaan Les actions peuvent en fait avoir autant d'effets secondaires, c'est littéralement leur but de gérer une logique non déterministe et asynchrone. Les mutations sont celles pour lesquelles il ne devrait strictement pas y avoir d'effets secondaires.

12voto

TitanFighter Points 1228

RÉPONSE INITIALE

Sur main.js (celui où l'on "installe" tous les modules et où l'on crée Vue instance, c'est-à-dire src/main.js ):

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

export { vm }

C'est mon exemple, mais dans notre cas, le plus important ici est const vm y router

Dans votre store :

import { vm } from '@/main'

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

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

P.P.S. Il semble que l'on puisse utiliser vm juste quand tout est chargé. En d'autres termes, nous ne pouvons pas utiliser vm à l'intérieur de someMutation dans ce cas, si nous appelons someMutation à l'intérieur de mounted() parce que mounted() vient/se produit avant vm est créé.


NOUVELLE RÉPONSE

Constantin réponse (celui qui a été accepté) est meilleur que le mien, donc je veux juste montrer aux novices comment l'implémenter.

Direction intérieure du noyau (intérieur /src dans mon cas), à côté de App.vue , main.js et d'autres que j'ai router.js avec le contenu :

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

Importez notre routeur vers 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 }

Enfin, à l'intérieur de votre composant, ou Vuex ou n'importe où ailleurs import router from './router' et faire ce dont vous avez besoin, comme router.push(...)

10voto

GuyC Points 4193

Il semble que vous n'injectez pas votre routeur dans votre application, d'où le fait qu'il soit "indéfini".

Dans les versions précédentes de vue-router, vous deviez : 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 tout au long de l'application


Après avoir répondu à une question connexe : Comment utiliser Vue Router à partir de l'état de 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 du routeur.

La première, plus directe, consiste à définir un global webpack pour l'instance.

La seconde implique l'utilisation de Promesses avec votre action vuex qui permettrait à vos composants d'utiliser leur référence à l'instance du routeur en suivant les actions Promise resolving / rejecting.

2 votes

Ceci devrait être la réponse spécifique à vue 2

7voto

Chris Jaynes Points 1527

Je n'aimais pas conserver l'état de l'emplacement de mon application séparément du reste de l'état de mon application dans le magasin, et devoir gérer à la fois un routeur et un magasin. J'ai donc créé un module Vuex qui gère l'état de l'emplacement. à l'intérieur de le magasin.

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

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

Cela présente l'avantage supplémentaire de faciliter la gestion de choses telles que les transitions de pages animées.

Ce n'est pas difficile de faire ses propres router module, mais vous pouvez aussi essayer le mien si vous voulez :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X