如何在vuex商店中使用vue-resource($ http)和vue-router($ route)? [英] How to use vue-resource ($http) and vue-router ($route) in a vuex store?

查看:165
本文介绍了如何在vuex商店中使用vue-resource($ http)和vue-router($ route)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我从组件的脚本中获取电影细节之前。该功能首先检查商店的电影ID是否与路线的参数电影ID相同。如果相同则不从服务器API获取电影,或者从服务器API获取电影。

Before I was getting movie detail from the component's script. The function first check whether the movie ID of the store is same as of the route's param movie ID. If its same then don't get the movie from the server API, or else get the movie from the server API.

它工作正常。但现在我正试图从商店的变异中获取电影细节。但是我收到错误

It was working fine. But now I am trying to get the movie details from the store's mutation. However I am getting error


未捕获的TypeError:无法读取未定义的属性'$ route'

Uncaught TypeError: Cannot read property '$route' of undefined

如何使用vue-router ($ route)访问params和vue-resource ( $ http)从vuex商店的服务器API获取?

How to use vue-router ($route) to access the params and vue-resource ($http) to get from the server API in vuex store?

store.js:

export default new Vuex.Store({
    state: {
        movieDetail: {},
    },
    mutations: {
        checkMovieStore(state) {
            const routerMovieId = this.$route.params.movieId;
            const storeMovieId = state.movieDetail.movie_id;
            if (routerMovieId != storeMovieId) {
                let url = "http://dev.site.com/api/movies/movie-list/" + routerMovieId + "/";
                this.$http.get(url)
                    .then((response) => {
                        state.movieDetail = response.data;
                    })
                    .catch((response) => {
                        console.log(response)
                    });
            }
        },
    },
});

组件脚本:

export default {
    computed: {
        movie() {
            return this.$store.state.movieDetail;
        }
    },
    created: function () {
        this.$store.commit('checkMovieStore');
    },
}


推荐答案

要在vuex商店中使用 $ http $ router ,您需要使用主vue实例。虽然我不建议使用它,但我会在回答实际问题后添加我推荐的内容。

To use $http or $router in your vuex store, you would need to use the main vue instance. Although I don't recommend using this, I'll add what I recommend after answering the actual question.

main.js 或无论您在何处创建vue实例如:

In your main.js or wherever you are creating your vue instance like:

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

或类似的东西,您可能还添加了 vue-router vue-resource 插件。

or something similar, you might also have added the vue-router and vue-resource plugins too.

对此进行略微修改:

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

我现在可以在vuex商店中导入它,如下所示:

I can now import it in vuex stores like so:

//vuex store:
import YourVueInstance from 'path/to/main'

checkMovieStore(state) {
const routerMovieId = YourVueInstance.$route.params.movieId;
const storeMovieId = state.movieDetail.movie_id;
if (routerMovieId != storeMovieId) {
  let url = "http://dev.site.com/api/movies/movie-list/" + routerMovieId + "/";
  YourVueInstance.$http.get(url)
    .then((response) => {
       state.movieDetail = response.data;
     })
     .catch((response) => {
       console.log(response)
     });
  }
}

以及 Austio ,这个方法应该是一个动作作为突变不是为处理异步而设计的。

and as the answer by Austio goes, this method should be an action as mutations are not designed to handle async.

现在采用推荐的方式。

Now coming to the recommended way of doing it.


  1. 您的组件可以访问路线params 并将其提供给操作

  1. Your component can access the route params and provide it to the action.

methods: {
  ...mapActions({
    doSomethingPls: ACTION_NAME
  }),
  getMyData () {
    this.doSomethingPls({id: this.$route.params})
  }
}


  • action 然后通过抽象的API服务文件进行调用(读取插件

  • The action then makes the call through an abstracted API service file (read plugins)

    [ACTION_NAME]: ({commit}, payload) {
       serviceWhichMakesApiCalls.someMethod(method='GET', payload)
         .then(data => {
            // Do something with data
         })
         .catch(err => {
            // handle the errors
         })
    }
    


  • 您的操作执行一些异步作业并将结果提供给亩tation

  • Your actions do some async job and provide the result to a mutation .

    serviceWhichMakesApiCalls.someMethod(method='GET', payload)
         .then(data => {
            // Do something with data
            commit(SOME_MUTATION, data)
         })
         .catch(err => {
            // handle the errors
         })
    


  • 变异应该是唯一修改你的

  • Mutations should be the only ones to modify your state.

    [SOME_MUTATION]: (state, payload) {
       state[yourProperty] = payload
    }
    







  • 示例
    包含端点列表的文件,如果需要,可能需要它你有不同的部署阶段,它们有不同的api端点,如:测试,升级,生产等。


    Example A file which contains a list of endpoints, you might need it if you have different stages of deployment which have different api endpoints like: test, staging, production, etc.

    export const ENDPOINTS = {
      TEST: {
        URL: 'https://jsonplaceholder.typicode.com/posts/1',
        METHOD: 'get'
      }
    }
    

    并且实现 Vue.http 的主文件为服务:

    And the main file which implements Vue.http as a service:

    import Vue from 'vue'
    import { ENDPOINTS } from './endpoints/'
    import { queryAdder } from './endpoints/helper'
    /**
    *   - ENDPOINTS is an object containing api endpoints for different stages.
    *   - Use the ENDPOINTS.<NAME>.URL    : to get the url for making the requests.
    *   - Use the ENDPOINTS.<NAME>.METHOD : to get the method for making the requests.
    *   - A promise is returned BUT all the required processing must happen here,
    *     the calling component must directly be able to use the 'error' or 'response'.
    */
    
    function transformRequest (ENDPOINT, query, data) {
      return (ENDPOINT.METHOD === 'get')
          ? Vue.http[ENDPOINT.METHOD](queryAdder(ENDPOINT.URL, query))
          : Vue.http[ENDPOINT.METHOD](queryAdder(ENDPOINT.URL, query), data)
    }
    
    function callEndpoint (ENDPOINT, data = null, query = null) {
      return new Promise((resolve, reject) => {
        transformRequest(ENDPOINT, query, data)
          .then(response => { return response.json() })
          .then(data => { resolve(data) })
          .catch(error => { reject(error) })
      })
    }
    
    export const APIService = {
      test () { return callEndpoint(ENDPOINTS.TEST) },
      login (data) { return callEndpoint(ENDPOINTS.LOGIN, data) }
    }
    

    queryAdder,如果它很重要,我用它来将params添加到url。

    The queryAdder in case it is important, I was using this to add params to the url.

    export function queryAdder (url, params) {
      if (params && typeof params === 'object' && !Array.isArray(params)) {
        let keys = Object.keys(params)
        if (keys.length > 0) {
          url += `${url}?`
          for (let [key, i] in keys) {
            if (keys.length - 1 !== i) {
              url += `${url}${key}=${params[key]}&`
            } else {
              url += `${url}${key}=${params[key]}`
            }
          }
        }
      }
      return url
    }
    

    这篇关于如何在vuex商店中使用vue-resource($ http)和vue-router($ route)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆