如何在 vuex 商店中使用 vue-resource ($http) 和 vue-router ($route)? [英] How to use vue-resource ($http) and vue-router ($route) in a vuex store?
问题描述
在我从组件的脚本中获取电影细节之前.该函数首先检查商店的电影 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
未捕获的类型错误:无法读取未定义的属性 '$route'
Uncaught TypeError: Cannot read property '$route' of undefined
如何使用 vue-router ($route)
访问 params 和 vue-resource ($http)
从 vuex store 中的服务器 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
,您需要使用 mainVue 实例.虽然我不推荐使用这个,但我会在回答实际问题后添加我推荐的内容.
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 的回答,这个方法应该是一个 action
作为 mutations
不是为了处理异步而设计的.
and as the answer by Austio goes, this method should be an action
as mutations
are not designed to handle async.
现在来到推荐的做法.
你的
component
可以访问route params
并将其提供给action
.
Your
component
can access theroute params
and provide it to theaction
.
methods: {
...mapActions({
doSomethingPls: ACTION_NAME
}),
getMyData () {
this.doSomethingPls({id: this.$route.params})
}
}
action
然后通过抽象的 API 服务文件(阅读plugins
)
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
})
}
你的 actions
做一些异步工作并将结果提供给 mutation
.
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
应该是唯一可以修改你的 state
的.
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 以防万一它很重要,我用它来向 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屋!