Vuex를 이용한 counter app 만들기
React를 공부하면서 배웠던 redux가 익숙해져버린 상황에서 처음 공부하는 vue는 어떤 식으로 component간의 data를 전달하는지 의문이 들던 차에 redux와 유사하게 직접 state를 변경하는 것이 아니라 action을 발생시키는 방식의 vuex라는 library가 있다는 것을 알게 되어 알아보게 되었다.
이번 포스팅에서는 redux를 학습할 때와 유사하게 vuex를 활용하여 counter app을 만들어 볼 것이다.
Vue.js 개발 환경을 구축해준 이후 vuex를 설치하여 개발을 이어갈 것이다.
$ npm i --save vuex
npm을 이용해 vuex를 설치한다.
// index.jsimport Vue from 'vue';
import store from './store';
import AppComponent from './components/AppComponent.vue';
new Vue({
el: '#app',
store,
render: h => h(AppComponent)
});
index.js에서는 <div id=”app”>에 AppComponent를 렌더링시킨다. 이 때 이전과는 달리 store option을 주어 생성한다.
store는 directory안의 js파일들로 구성되어 있다.
먼저 이 js파일들을 최종적으로 통합해주는 index.js파일에 대해 먼저 살펴보면
// store/index.jsimport Vue from 'vue'
import Vuex from 'vuex'
import * as getters from './getters'
import * as actions from './actions'
import * as mutations from './mutations'
Vue.use(Vuex);
const state = {
count: 0,
history: []
};
const store = new Vuex.Store({
state,
getters,
actions,
mutations
});
export default store;
counter app에서 관리하는 state는 count와 history 두 가지이다.
index.js외의 store 내 js파일은
actions.js, getters.js, mutations.js 세 가지이다.
actions는 increment와 decrement등 함수를 가지고 있으면 redux의 dispatch와 유사하게 측정 action을 commit시킨다.
// store/getter.jsexport const count = state => state.count;
const limit = 5;
export const recentHistory = state => {
const end = state.history.length;
const begin = end - limit < 0 ? 0 : end - limit;
return state.history
.slice(begin, end)
.join(', ')
};
getter에서는 state를 전달받아 현재 state를 기반으로 새로운 state를 갱신해준다. state.history의 끝에서부터 5개 까지만을 history로 관리하게 한다.
// store/mutations.jsexport const increment = state => {
state.count++;
state.history.push('increment');
};
export const decrement = state => {
state.count--;
state.history.push('decrement');
};
mutaions는 실제로 state의 상태를 변경하는 유일한 영역이다. increment일 경우 state.count를 증가시키고 history에 ‘increment’를 추가하며, decrement일때는 반대로 state.count를 감소시키고 history에 ‘decrement’를 추가시킨다.
//components/AppComponent.vue<template>
<div class="counter">
Value: {{ count }}
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementIfOdd">Increment if odd</button>
<button @click="incrementAsync">Increment async</button>
<div>
<div>Recent History (last 5 entries): {{ recentHistory }}</div>
</div>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
export default {
computed: mapGetters([
'count',
'recentHistory'
]),
methods: mapActions([
'increment',
'decrement',
'incrementIfOdd',
'incrementAsync'
])
}
</script>
AppComponent에서는 현재 state.count를 보여주고 increment, decrement, incrementIfOdd, incrementAsync 4가지의 버튼을 가지고 있다.
computed는 redux의 mapStateToProps와 같이 실제 view에서 사용할 state값들이고 mapActions는 mapStateToDispatch와 같이 state를 변경하도록 action을 실행해주는 functions(actions.js)가 들어간다.