コンポーネントのスクリプトから映画の詳細を取得する前。この関数はまず、ストアのムービーIDがルートのパラメータームービーIDと同じであるかどうかを確認します。同じ場合は、サーバーAPIから映画を取得しないか、サーバーAPIから映画を取得します。
正常に動作していました。しかし今、私は店の突然変異から映画の詳細を取得しようとしています。しかし、私はエラーが発生しています
Uncaught TypeError:未定義のプロパティ '$ route'を読み取れません
Vue-routerの使用方法($route)
パラメータとvue-resourceにアクセスするには($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');
},
}
Vuexストアで$http
または$router
を使用するには、メインの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
は非同期を処理するように設計されていないため、このメソッドはmutations
である必要があります。
今それを行うための推奨される方法に来ています。
component
はroute params
にアクセスして、それをaction
に提供できます。
methods: {
...mapActions({
doSomethingPls: ACTION_NAME
}),
getMyData () {
this.doSomethingPls({id: this.$route.params})
}
}
次に、action
は、抽象化されたAPIサービスファイルを介して呼び出しを行います( read 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インスタンス内でそれらにアクセスすることはできません。また、ミューテーションは同期しています。必要なのはアクションです。
突然変異=>状態といくつかの引数を与えて状態を突然変異させる関数
アクション=> 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);
},
これで、作成した関数は、http呼び出しを行うidを使用してcheckMovieStoreアクションをディスパッチします。これが完了すると、ストアが値で更新されます。
axios をvuexモジュール(ストアとサブモジュール)にインポートし、それをhttpリクエストに使用することを強くお勧めします
ストア内のvueインスタンスにアクセスするには、this._vm
を使用します。
しかし、Amreshがアドバイスしたように、vuexでは$router
のようなものを使用しないでください