저는 최근에 jQ에서 VueJS 인보다 구조화 된 프레임 워크로 마이그레이션하기 시작했습니다.
개념적으로 Vuex는 저에게 약간의 패러다임 전환 이었지만 지금은 그 모든 것이 무엇인지 알고 있으며 완전히 이해합니다! 그러나 대부분 구현 관점에서 볼 때 약간의 회색 영역이 있습니다.
이것은 디자인 상 좋지만 단방향 데이터 흐름 의 Vuex 주기 와 모순되는지 모르겠습니다 .
기본적으로 액션에서 promise (유사) 객체를 반환하는 것이 좋은 방법으로 간주됩니까? 나는 이것을 실패 상태 등의 비동기 래퍼로 취급하므로 약속을 반환하기에 적합한 것처럼 보입니다. 반대로 뮤 테이터는 단지 사물을 변경하고 스토어 / 모듈 내의 순수한 구조입니다.
답변
actions
Vuex에서는 비동기식입니다. 호출 함수 (동작 개시 자)가 동작이 완료되었음을 알 수 있도록하는 유일한 방법은 Promise를 반환하고 나중에 해결하는 것입니다.
예를 들면 다음과 같습니다.를 myAction
반환하고 Promise
, http 호출을 수행하고, Promise
나중을 확인 하거나 거부합니다. 모두 비동기 적으로
actions: {
myAction(context, data) {
return new Promise((resolve, reject) => {
// Do something here... lets say, a http call using vue-resource
this.$http("/api/something").then(response => {
// http success, call the mutator and change something in state
resolve(response); // Let the calling function know that http is done. You may send some data back
}, error => {
// http failed, let the calling function know that action did not work out
reject(error);
})
})
}
}
이제 Vue 구성 요소가를 시작 myAction
하면이 Promise 개체를 가져와 성공 여부를 알 수 있습니다. 다음은 Vue 구성 요소의 샘플 코드입니다.
export default {
mounted: function() {
// This component just got created. Lets fetch some data here using an action
this.$store.dispatch("myAction").then(response => {
console.log("Got some data, now lets show something in this component")
}, error => {
console.error("Got nothing from server. Prompt user to check internet connection and try again")
})
}
}
위에서 볼 수 있듯이,을 위해 매우 유용합니다 actions
를 반환 Promise
. 그렇지 않으면 액션 개시자가 무슨 일이 일어나고 있는지 그리고 사용자 인터페이스에 무언가를 보여줄만큼 안정된시기를 알 수있는 방법이 없습니다.
그리고 마지막 메모 mutators
-당신이 올바르게 지적했듯이 그들은 동 기적입니다. 그들은에서 항목을 변경 state
하고 일반적으로에서 호출됩니다 actions
. 혼합 할 필요가 없습니다 Promises
으로 mutators
는 AS, actions
그 부분 핸들.
편집 : 단방향 데이터 흐름의 Vuex주기에 대한 내 견해 :
this.$store.state["your data key"]
구성 요소에서 와 같이 데이터에 액세스하는 경우 데이터 흐름은 단방향입니다.
작업의 약속은 구성 요소에 작업이 완료되었음을 알리는 것입니다.
구성 요소는 위 예제의 약속 해결 기능에서 데이터를 가져 오거나 ( $store.state["your data key"]
단방향이 아니므로 권장하지 않음) 직접 단방향이고 vuex 데이터 수명주기를 따릅니다.
위의 단락은 Vue.set(state, "your data key", http_data)
http 호출이 작업에서 완료되면 mutator가를 사용한다고 가정합니다 .
답변
닫힌 주제에 대한 정보를 위해 :
약속을 만들 필요가 없습니다. axios는 약속을 직접 반환합니다.
예:
export const loginForm = ({ commit }, data) => {
return axios
.post('http://localhost:8000/api/login', data)
.then((response) => {
commit('logUserIn', response.data);
})
.catch((error) => {
commit('unAuthorisedUser', { error:error.response.data });
})
}
다른 예시:
addEmployee({ commit, state }) {
return insertEmployee(state.employee)
.then(result => {
commit('setEmployee', result.data);
return result.data; // resolve
})
.catch(err => {
throw err.response.data; // reject
})
}
async-await 를 사용한 또 다른 예
async getUser({ commit }) {
try {
const currentUser = await axios.get('/user/current')
commit('setUser', currentUser)
return currentUser
} catch (err) {
commit('setUser', null)
throw 'Unable to fetch current user'
}
},
답변
행위
ADD_PRODUCT : (context,product) => {
return Axios.post(uri, product).then((response) => {
if (response.status === 'success') {
context.commit('SET_PRODUCT',response.data.data)
}
return response.data
});
});
구성 요소
this.$store.dispatch('ADD_PRODUCT',data).then((res) => {
if (res.status === 'success') {
// write your success actions here....
} else {
// write your error actions here...
}
})
답변
TL : DR; 필요한 경우에만 작업에서 약속을 반환하지만 동일한 작업을 DRY 연결합니다.
오랜 시간 동안 나는 그 반환 작업이 단방향 데이터 흐름의 Vuex주기와 모순 되기는하지만.
하지만 EDGE CASES가 있습니다. 당신의 행동에서 약속을 돌려주는 것이 “필요한” 가 있습니다.
두 가지 다른 구성 요소에서 작업이 트리거 될 수 있고 각각 실패 사례를 다르게 처리하는 상황을 상상해보십시오. 이 경우 호출자 구성 요소를 매개 변수로 전달하여 상점에서 다른 플래그를 설정해야합니다.
멍청한 예
사용자가 navbar 및 / profile 페이지 (navbar 포함)에서 사용자 이름을 편집 할 수있는 페이지입니다. 둘 다 비동기식 인 “사용자 이름 변경”작업을 트리거합니다. 약속이 실패하면 페이지는 사용자가 사용자 이름을 변경하려는 구성 요소에만 오류를 표시해야합니다.
물론 멍청한 예이지만 코드를 복제하고 두 가지 다른 작업에서 동일한 호출을하지 않고는이 문제를 해결할 수있는 방법이 없습니다.
답변
actions.js
const axios = require('axios');
const types = require('./types');
export const actions = {
GET_CONTENT({commit}){
axios.get(`${URL}`)
.then(doc =>{
const content = doc.data;
commit(types.SET_CONTENT , content);
setTimeout(() =>{
commit(types.IS_LOADING , false);
} , 1000);
}).catch(err =>{
console.log(err);
});
},
}
home.vue
<script>
import {value , onCreated} from "vue-function-api";
import {useState, useStore} from "@u3u/vue-hooks";
export default {
name: 'home',
setup(){
const store = useStore();
const state = {
...useState(["content" , "isLoading"])
};
onCreated(() =>{
store.value.dispatch("GET_CONTENT" );
});
return{
...state,
}
}
};
</script>