Как использовать Vue-ресурс ($http) и Vue-маршрутизатор ($route) в магазине vuex?
прежде чем я получал детали фильма из сценария компонента. Функция сначала проверяет, совпадает ли идентификатор фильма магазина с идентификатором фильма маршрута. Если это то же самое, то не получите фильм из API сервера или получите фильм из API сервера.
Он работал хорошо. Но теперь я пытаюсь получить детали фильма из мутации магазина. Однако я получаю ошибку
Uncaught TypeError: не удается прочитать свойство "$route" неопределено
как использовать vue-router ($route)
для доступа к params и Vue-resource ($http)
получить от API сервера в магазине vuex?
магазине.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');
},
}
2 ответов
использовать $http
или $router
в вашем магазине vuex вам нужно будет использовать основной экземпляр vue. Хотя я не рекомендую использовать это, я добавлю то, что я рекомендую после ответа на фактический вопрос.
в своем main.js
или где бы вы ни создавали свой экземпляр vue, например:
new Vue({
el: '#app',
router,
store,
template: '<App><App/>',
components: {
App
}
})
или что-то подобное, вы могли бы также добавил vue-router
и vue-resource
тоже Плагины.
небольшая модификация это:
export default 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)
});
}
}
и ответ Austio идет, этот метод должен быть action
as mutations
не предназначены для обработки асинхронных.
теперь переходим к рекомендуемому способу сделать это.
-
код
component
открытьroute params
и предоставить его вaction
.methods: { ...mapActions({ doSomethingPls: ACTION_NAME }), getMyData () { this.doSomethingPls({id: this.$route.params}) } }
-
на
action
затем делает вызов через абстрактный файл службы API (читатьplugins
)[ACTION_NAME]: ({commit}, payload) { serviceWhichMakesApiCalls.someMethod(method='GET', payload) .then(data => { // Do something with data }) .catch(err => { // handle the errors }) }
-
код
actions
выполните асинхронное задание и предоставьте результатmutation
.serviceWhichMakesApiCalls.someMethod(method='GET', payload) .then(data => { // Do something with data commit(SOME_MUTATION, data) }) .catch(err => { // handle the errors })
-
Mutations
надо только изменить свойstate
.[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) }
}
queryAdder в случае, если это важно, я использовал это для добавления параметров в 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
}
Итак, несколько вещей, $store и $route являются свойствами экземпляра Vue, поэтому доступ к ним внутри экземпляра Vuex не работает. Кроме того, мутации синхронны, что вам нужно, это действия
Mutations => функция, которая заданное состояние и некоторые аргументы мутирует состояние
Action => сделайте асинхронные вещи, такие как http-вызовы, а затем зафиксируйте результаты мутации
чтобы создать действие, которое отправляет http. Имейте в виду, что это псевдокод.
//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);
},
теперь ваша созданная функция отправляет действие checkMovieStore с идентификатором, который выполняет вызов http, как только он будет завершен, он обновляет хранилище со значением.