2017-03-02 5 views
6

전에 구성 요소의 스크립트에서 영화 세부 정보를 가져 왔습니다. 이 함수는 먼저 상점의 무비 ID가 경로의 param 무비 ID와 같은지 확인합니다. 그것과 같으면 서버 API에서 영화를 가져 오지 마십시오. 그렇지 않으면 서버 API에서 영화를 가져옵니다.

괜찮 았습니다. 하지만 이제는 상점의 변이에서 영화 세부 정보를 얻으려고합니다. 그러나 나는 오류

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

방법 vuex 저장소에 서버 API에서 얻을 수있는 PARAMS 및 VUE-자원 ($http)에 액세스 할 수 VUE 라우터 ($route)을 사용하기는 무엇입니까?

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'); 
    }, 
} 

답변

5

vuex 저장소에 $http 또는 $router을 사용하려면 기본 vue 인스턴스를 사용해야합니다. 이 방법을 사용하지 않는 것이 좋지만 실제 질문에 답한 후에 내가 추천하는 것을 추가 할 것입니다.

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

또는 이와 유사한, 당신은 또한 vue-routervue-resource 플러그인도 추가했을 수 : 당신의 main.js 어디든지처럼 VUE 인스턴스를 만드는에서


. 여기에 약간의 수정을하는

:

//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해야한다 :

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

지금과 같이 vuex 상점에서 가져올 수 있습니다 mutations은 비동기를 처리하도록 설계되지 않았습니다.


이제 권장 방법이 있습니다.

  1. 귀하의 componentroute params 액세스가 action에 제공 할 수 있습니다.

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

    다음 추상화 된 API 서비스 파일
    [ACTION_NAME]: ({commit}, payload) { 
        serviceWhichMakesApiCalls.someMethod(method='GET', payload) 
        .then(data => { 
         // Do something with data 
        }) 
        .catch(err => { 
         // handle the errors 
        }) 
    } 
    
  3. (read plugins)

    통해 호출을 귀하의 actions 일부 비동기 일을하고 mutation에 결과를 제공합니다.

    serviceWhichMakesApiCalls.someMethod(method='GET', payload) 
        .then(data => { 
         // Do something with data 
         commit(SOME_MUTATION, data) 
        }) 
        .catch(err => { 
         // handle the errors 
        }) 
    
  4. Mutationsstate를 수정할 수있는 유일한 사람이어야한다.

    [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를 사용하여 urams에 params를 추가했습니다.

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 
} 
+0

변수를 사용하여 작업에서 주 통계 인스턴스를 참조했습니다. 이 액션은, 컴퍼넌트의 작성 후크 중에 불려갑니다. 이 시점에서 주 통계 인스턴스에 대한 참조를 사용할 수 없으므로 예외가 발생합니다. – Teddy

+0

이것은 브라우저 재로드 버튼을 클릭 할 때 해당 구성 요소가 해당 라우트에 처음으로로드 된 경우에만 발생합니다. 앱이 이미로드 된 경우 해당 구성 요소로 이동하면 문제가 없습니다. 그 해결 방법이 있습니까? – Teddy

+0

TypeError : 정의되지 않은 '$ http'속성을 읽을 수 없습니다. – Teddy

2

그래서 몇 가지, $ 저장소와 $ 경로가있는 뷰 인스턴스의 속성 왜 내부를 액세스하는 Vuex 인스턴스가 작동하지 않습니다. 또한, 돌연변이는 행동이

  1. 상태를 부여 => 함수 돌연변이 일부 인수가 상태를 변이합니다입니다 필요 synchonous 있습니다

  2. 액션 => 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 조치를 전달합니다.