Vuex 란?
What is Vuex?
Vuex 시작하기
Mutaions는 순차적인 동기적 로직만 선언하고 Actions에는 비순차적인 비동기 처리 로직을 선언한다.
Mutations에 대해 짚어보면, Mutaions의 역할은 State(데이터)관리에 주안점을 두고 있다. 상태 관리 자체가 한 데이터에 대해 여러 개의 컴포넌트가 관여하는 것을 효율적으로 관리하기 위함인데, Mutations에 비동기 처리 로직들이 포함되면, 같은 값에 대해 여러 개의 컴포넌트에서 변경 요청을 했을 때 그 변경 순서 파악이 어렵기 때문에, setTimeout()이나 서버와의 http 통신 처리 같은 결과를 받아 올 타이밍이 예측되지 않는 로직은 Actions에 선언한다.
actions 역시 비동기적 상태를 추적하기 때문에 commit을 사용한다.
actions를 선언하고, actions methods를 추가해준다.
// store.js
export const store = new Vuex.Store({
state: {
counter: 0;
},
mutations: {
addcounter(state, payload({
return state.counter++;
}
},
actions: {
// commit의 대상인 addCounter는 mutations의 메서드를 의미한다.
addCounter(context){
return context.commit('addCounter');
}
}
})
상태가 변화하는 걸 추적하기 위해 actions는 mutaions의 메서드를 호출(commit)하는 구조가 된다.
아래처럼 HTTP get 요청이나, setTimeout 과 같은 비동기 처리 로직들은 actions에 선언해준다!
// store.js
export const store = new Vuex.Store({
actions: {
getServerData: function (context) {
return axios.get("sample.json").then(function() {
// ...
});
},
delayFewMinutes: function (context) {
return setTimeout(function () {
commit('addCounter');
}, 1000);
}
}
});
actions의 context는 무엇일까?
console.log(context)
를 해보면, state / getters 를 모두 포함한 Object임을 알 수 있다. 이 Object는 현재 저장소(store) 인스턴스의 같은 메소드/프로퍼티 세트를 나타내는 Vuex 컨텍스트 객체이다.
context.getters, context.state를 여러번 써주지 않기 위해서 구조분해할당을 사용할 수 있다.
addCounter: function ({commit}) {
return commit('addCounter');
}
현재 컴포넌트 methods에서 actions 메소드를 호출하는 방법은 아래와 같다.
// counter.vue
methods: {
increaseCnt() {
this.$store.dispatch('addCounter');
}
},
mutations에서는 컴포넌트 methods에서 commit을 사용했지만, actions는 dispatch를 사용한다.
mutations은 추적이 가능한 상태 변이를 명시적으로 호출하기 위해 commit을 사용한다. 이 commit은 사용하는 즉시 상태 변이가 실행된다.(동기적)
dispatch는 이런 commit을 비동기적으로 관리할 수 있게 한다. action 내에 정의된 commit의 호출 시기를 비동기적으로 지정한다는 의미이다.
// store.js
actions: {
incrementAsync ({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}
// counter.vue
methods: {
increaseCnt(){
this.$store.dispatch('incrementAsnyc');
}
}
actions는 mutations + commit 을 믹스해 둔 것이라고 할 수 있다. actions는 mutations와 마찬가지로 전달인자를 받을 수 있고, type 속성을 포함한 객체를 받을수도 있다.
// 페이로드(전달인자)와 함께 디스패치
store.dispatch('incrementAsync', {
amount: 10
})
// type속성을 포함한 객체와 함께 디스패치
store.dispatch({
type: 'incrementAsync',
amount: 10
})
// counter.vue
// by 와 duration 등의 여러 인자 값을 넘길 경우, 객체안에 key - value 형태로 여러 값을 넘길 수 있다
<button @click="asyncIncrement({ by: 50, duration: 500 })">Increment</button>
// store.js
// ...
actions: {
// payload 는 일반적으로 사용하는 인자 명
asyncIncrement: function (context, payload) {
return setTimeout(function () {
context.commit('increment', payload.by);
}, payload.duration);
}
}
mapGetters, mapMutaions helper 함수들과 마찬가지로, mapActions도 동일한 방식으로 사용할 수 있다.
import { mapActions } from 'vuex'
export default{
methods:{
...mapActions([
'asyncIncrement'
'asyncDecrement',
])
}
}