【问题标题】:How to navigate using vue router from Vuex actions如何在 Vuex 操作中使用 Vue 路由器进行导航
【发布时间】:2017-04-05 19:54:43
【问题描述】:

我正在使用 Vue 2.x 和 Vuex 2.x 创建一个 Web 应用程序。我正在通过 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:"/"}) 给了我以下错误。

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

如何做到这一点。

模拟 JsFiddle:here

【问题讨论】:

  • 这是因为您在将“this”视为文字的箭头函数中使用它。将其转换为常规函数或使用下面的建议答案...

标签: javascript vue.js vuex


【解决方案1】:

import router from './router'

并使用router.push

就这么简单。

【讨论】:

    【解决方案2】:

    您似乎没有将路由器注入您的应用程序,因此它是“未定义的”

    在以前的 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 的形式使用


    在回答相关问题后:How to use Vue Router from Vuex state? 似乎 Vuex 不会在this.$router 接收路由器实例。因此,建议使用两种方法来提供对路由器实例的访问。

    第一个更直接,它涉及为实例设置一个全局 webpack。

    第二个涉及将 Promises 与您的 vuex 操作一起使用,这将允许您的组件在 Promise 解析/拒绝操作之后利用它们对路由器实例的引用。

    【讨论】:

    • 这应该是专门针对 vue 2 的答案
    【解决方案3】:

    这个例子可能会对你有所帮助。

    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 不太正确,即使是 vuex 演示中的操作也有副作用。
    • @adriaan 动作实际上可以有很多副作用,实际上它们的目的是处理非确定性和异步逻辑。突变是严格来说应该没有副作用的。
    • 我想我的评论是无效的。感谢您清除它!
    • @adriaan 你在考虑突变和吸气剂
    【解决方案4】:

    我不喜欢将我的应用程序的位置状态与商店中的其他应用程序状态分开,并且必须同时管理路由器和商店,因此我创建了一个管理位置状态的 Vuex 模块在商店内。

    现在我可以通过调度操作进行导航,就像任何其他状态更改一样:

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

    这还有一个额外的好处,就是让动画页面转换之类的事情更容易处理。

    推出自己的router 模块并不难,但如果你愿意,也可以试试我的:

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

    【讨论】:

      【解决方案5】:

      初步回答

      main.js(我们“安装”所有模块并创建Vue 实例的地方,即src/main.js):

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

      这是我的例子,但在我们的例子中,这里最重要的是 const vmrouter

      在你的store:

      import { vm } from '@/main'
      
      yourMutation (state, someRouteName) {
        vm.$router.push({name: someRouteName})
      }
      

      附:使用import { vm } from '@/main',我们可以访问Vuex 中我们需要的任何内容,例如vm.$root,这是bootstrap-vue 的某些组件所需要的。

      P.P.S.似乎我们可以在加载所有内容时使用vm。换句话说,如果我们在mounted() 中调用someMutation,我们不能在someMutation 中使用vm,因为mounted()vm 被创建之前出现/出现。


      新答案

      Constantin 的answer(接受的那个)比我的好,所以只想给新手演示一下如何实现。

      在核心目录内(在我的情况下是在 /src 内),在 App.vuemain.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(...)

      【讨论】:

        【解决方案6】:

        您可以像这样简单地从路由器目录导入路由:

        import router from '@/router'
        
        router.push({name: 'Home'})
        

        这个 @ 符号替换了 src 目录的路径

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-08-19
          • 2018-07-04
          • 2017-02-12
          • 2022-07-12
          • 2019-03-18
          • 2018-11-22
          • 2021-04-28
          相关资源
          最近更新 更多