Як здійснювати навігацію за допомогою маршрутизатора vue від дій Vuex


78

Я створюю веб-програму з Vue 2.x та Vuex 2.x. Я отримую деяку інформацію з віддаленого місця за допомогою виклику http, я хочу, щоб у разі невдалого виклику я мав перенаправити на якусь іншу сторінку.

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

Але this.$router.push({path:"/"})мені видається така помилка.

Невпійманий (обіцяно) TypeError: Не вдається прочитати властивість 'push' з undefined

Як цього можна досягти.

Імітований JsFiddle: тут


це тому, що ви використовуєте його всередині функції зі стрілкою, яка розглядає це як літерал. або перетворіть його на звичайну функцію, або скористайтесь запропонованими відповідями нижче ...
EldadT

Відповіді:


170

import router from './router'

і використовувати router.push

Просто так.


1
Зверніть увагу, що я імпортував його в модулях, тому мені знадобилося пару секунд, щоб помітити, що шлях маршрутизатора має бути таким: "../../router/"
Fathy

16

Цей приклад може вам допомогти.

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

Ви не повинні використовувати Vue. Дії не повинні мати побічних ефектів. Вирішіть це методами такого компонента, якdispatch('someAction').then(() => this.$router.push('/welcome'))
adriaan

2
@adriaan не дуже точно, навіть дії у демонстраціях vuex мають побічні ефекти.
Blowsie

11

Схоже, ви не вводите свій маршрутизатор у свій додаток, отже, він є "невизначеним"

У попередніх версіях vue-router ви мали б:, за Vue.use(VueRouter)допомогою 2.0 ви можете ввести маршрутизатор у програму, як показано нижче:

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

const router = new VueRouter({
  routes
})

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

це повинно зробити його доступним як this.$routerу всьому додатку


Відповідаючи на відповідне питання: Як використовувати Vue Router із стану Vuex? здається, Vuex не отримає екземпляр маршрутизатора за адресою this.$router. Тому було запропоновано два методи для забезпечення доступу до екземпляра маршрутизатора.

Перший є більш прямим, що передбачає встановлення глобального веб-пакета для екземпляра.

Другий передбачає використання Promises з вашою дією vuex, що дозволить вашим компонентам використовувати посилання на екземпляр маршрутизатора після дій Promise вирішення / відхилення.


2
Це має бути конкретно відповіддю на Vue 2
17:17,

6

ПОЧАТКОВА ВІДПОВІДЬ

У main.js(той, де ми "встановлюємо" всі модулі і створюємо Vueекземпляр, тобто src/main.js):

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

export { vm }

Це мій приклад, але в нашому випадку найголовнішим тут є const vmіrouter

У вашому store:

import { vm } from '@/main'

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

PS Використовуючи import { vm } from '@/main'ми можемо отримати доступ до всього, що нам потрібно Vuex, наприклад, vm.$rootщо потрібно деяким компонентам bootstrap-vue.

PPS Здається, ми можемо використовувати vmсаме тоді, коли все завантажено. Іншими словами, ми не можемо використовувати vmвсередині someMutation, якщо ми зателефонуємо someMutationвсередину mounted(), тому що mounted()приходить / відбувається до того, vmяк створено.


НОВА ВІДПОВІДЬ

Constantin в відповідь (Прийнята один) краще , ніж у мене, так що просто хочу , щоб показати новачкові , як реалізувати його.

Всередині ядра реж (всередині /srcв моєму випадку), поруч App.vue, main.jsі інші у мене є router.jsз вмістом:

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

Імпортуйте наш маршрутизатор до 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 }

Нарешті, всередині вашого компонента, або Vuex, або де-небудь ще, import router from './router'і робіть все, що вам потрібно, наприкладrouter.push(...)


5

Мені не сподобалось тримати стан місцезнаходження мого додатка окремо від решти стану мого додатка в магазині, а також керувати маршрутизатором і магазином, тому я створив модуль Vuex, який управляє станом розташування всередині магазину.

Тепер я можу орієнтуватися, надсилаючи дії, як і будь-яка інша зміна стану:

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

Це має додаткову перевагу, завдяки якій такі речі, як анімовані переходи сторінок, є простішими в обробці.

Не складно прокрутити власний routerмодуль, але ви також можете спробувати мій, якщо хочете:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.