Javascript 如何在vuex存储中使用vue资源($http)和vue路由器($route)?
在我从组件的脚本中获取电影细节之前。该函数首先检查存储区的电影ID是否与路由的param电影ID相同。如果相同,则不从服务器API获取电影,否则从服务器API获取电影 它工作得很好。但现在我正试图从商店的突变中了解电影的细节。然而,我得到了错误 未捕获的TypeError:无法读取未定义的属性“$route” 如何使用vue路由器Javascript 如何在vuex存储中使用vue资源($http)和vue路由器($route)?,javascript,vuejs2,vue-router,vue-resource,vuex,Javascript,Vuejs2,Vue Router,Vue Resource,Vuex,在我从组件的脚本中获取电影细节之前。该函数首先检查存储区的电影ID是否与路由的param电影ID相同。如果相同,则不从服务器API获取电影,否则从服务器API获取电影 它工作得很好。但现在我正试图从商店的突变中了解电影的细节。然而,我得到了错误 未捕获的TypeError:无法读取未定义的属性“$route” 如何使用vue路由器($route)访问参数,以及如何使用vue资源($http)从vuex存储中的服务器API获取数据 store.js: export default new Vuex
($route)
访问参数,以及如何使用vue资源($http)
从vuex存储中的服务器API获取数据
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');
},
}
所以有几件事,$store和$route是Vue实例的属性,这就是为什么在Vuex实例中访问它们不起作用的原因。此外,突变是同步的,你需要的是行动
//action in store
checkMovieStore(store, id) {
return $http(id)
.then(response => store.commit({ type: 'movieUpdate', payload: response })
}
//mutation in store
movieUpdate(state, payload) {
//actually set the state here
Vue.set(state.payload, payload)
}
// created function in component
created: function () {
return this.$store.dispatch('checkMovieStore', this.$route.params.id);
},
现在,您创建的函数使用id分派checkMovieStore操作,该操作执行http调用,一旦完成,它将用值更新存储。要在vuex存储中使用
$http
或$router
,您需要使用主vue实例。虽然我不建议使用此选项,但我会在回答实际问题后添加我的建议
在您的
main.js
中或在创建vue实例的任何地方,如:
new Vue({
el: '#app',
router,
store,
template: '<App><App/>',
components: {
App
}
})
我现在可以在vuex商店中导入它,如下所示:
//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)
});
}
}
答案是,这种方法应该是一种操作
,因为突变
不是为处理异步而设计的
现在来看看推荐的方法
组件
可以访问路由参数
,并将其提供给操作
methods: {
...mapActions({
doSomethingPls: ACTION_NAME
}),
getMyData () {
this.doSomethingPls({id: this.$route.params})
}
}
操作
然后通过一个抽象的API服务文件()进行调用
操作
执行一些异步工作,并将结果提供给变异
serviceWhichMakesApiCalls.someMethod(method='GET', payload)
.then(data => {
// Do something with data
commit(SOME_MUTATION, data)
})
.catch(err => {
// handle the errors
})
突变
应该是唯一可以修改您的状态
的突变
[SOME_MUTATION]: (state, payload) {
state[yourProperty] = payload
}
示例 一个包含端点列表的文件,如果部署的不同阶段具有不同的api端点(如:测试、暂存、生产等),则可能需要该文件
export const ENDPOINTS = {
TEST: {
URL: 'https://jsonplaceholder.typicode.com/posts/1',
METHOD: 'get'
}
}
以及将Vue.http
作为服务实现的主文件:
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) }
}
要访问存储区中的vue实例,请使用
this.\u vm
但正如Amresh所建议的,不要在vuex中使用类似于
$router的东西,我强烈建议在vuex模块(存储和子模块)上导入,并将其用于vuex存储中的http请求:
import Vue from 'vue'
Vue.http.post('url',{})
与普通vue组件不同:
this.$http.post(…)
我在一个操作中使用了一个变量来引用主vue实例。在创建组件的钩子期间调用该操作。此时,对主vue实例的引用不可用,这会导致异常。只有当用户单击“浏览器重新加载”按钮时,该组件恰好是该路由上加载的第一个组件时,才会发生这种情况。如果应用程序已经加载,导航到该组件可以正常工作。在这种情况下有什么解决方法吗?您是否尝试过我添加的推荐方法?使用实例不是使用$http的好方法。我还没有弄清楚如何使用它。一些官方示例使用store和api服务,但它们只使用Mock而不是http请求。有可用的链接吗?YourVueInstance.$http不起作用,但Vue.http起作用。为什么?我不明白为什么axios
总是更好的答案。你能提供一个为什么axios在这种特殊情况下更好的原因吗?主要原因是社区,你会发现更容易找到解决此类问题的方法。也许,我的观点是:也许可以提供为什么你会推荐另一个lib给这个人实际询问的lib。如果你问“我的车抛锚了,有人能帮忙吗?”有人过来说“你应该换一辆不同的车”,你会有什么感觉
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) }
}
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
}
import Vue from 'vue'
Vue.http.post('url',{})