Vuex(상태관리 패턴)
in Javascript
Typescript 기준으로 작성되어 있습니다.
Vuex 란??
vue.js 애플리케이션에서 상태관리 패턴을 지원하는 라이브러리입니다. 중앙 집중식 저장소 역할으로 상태(state)를 지원하는 옵션을 통해 상태를 변경하거나, 계산하여 사용할 수 있습니다. 비슷한 상태관리 패턴 지원 라이브러리인 react redux(리덕스)
가 있습니다.
사용하는 이유
- 중앙 집중식으로 데이터의 움직임을 한 눈에 확인할 수 있다.
- 프로젝트가 커지거나 부모, 자식 관계에 관계가 복잡해지면 데이터을 확인하거나 이해하기 어려운 것과 유지보수가 힘들어지는 것을 개선 가능
패턴
상태(state), 화면(view), 변경(actions) 단방향 데이터 흐름으로 처리됩니다.
State(Data)
컴포넌트 간에 공유할 데이터입니다.
Getter(Computed)
vuex의 state를 가져올때 사용, 계산하여 가져올 수 도 있습니다.
Mutations(Methods)
vuex의 state를 변경할때 사용
Actions(Methods 비동기)
vuex의 mutations을 커밋할수 있고, 작업에 비동기 작업을 포함할 수 있다.
사용법
먼저 RootState
루트 저장소를 만들어 줍니다. 최상위 저장소로 modules
에 선언된 저장소 간 state를 공유가 가능합니다.
// file: "/src/store/index.ts"
import Vue from 'vue'
import Vuex, { StoreOptions } from 'vuex'
import dog from './dog'
Vue.use(Vuex)
export interface RootState {
key: string
}
const store: StoreOptions<RootState> = {
state: {
key: 'value'
},
actions: {
changeKey (context, payload: string) {
context.commit('setKey', payload)
}
},
mutations: {
setKey (state, payload: string) {
state.key = payload
}
},
getters: {
key (state): string {
return state.key
}
}
modules: {
dog
}
}
export default new Vuex.Store<RootState>(store)
예시로 dog
라는 저장소 모듈를 만들어 보았습니다. 제네릭 타입에 dogState
와 RootState
를 넘겨주어 타입을 추론할 수 있게 한다.
// file: "/src/state/dog/index.ts"
import { Module } from 'vuex'
import { RootState } from '@/store'
interface dogState {
name: string
age: number
}
const dog: Module<dogState, RootState> = {
namespaced: true,
state: {
name: 'spring',
age: 5
},
actions: {
replaceDog (context, { name, age }: dogState) {
context.commit('setName', name)
context.commit('setAge', age)
}
},
mutations: {
setName (state, payload: string) {
state.name = payload
},
setAge (state, payload: number) {
state.age = payload
}
},
getters: {
name (state) {
return state.name
},
age (state) {
return state.age
}
}
}
export default dog
이렇게 만든 로트 저장소를 main.ts
에 등록해줍니다.
// file: "/src/main.ts"
import Vue from 'vue'
import App from './App.vue'
import state from './state'
new Vue({
el: '#app',
state,
template: '<App />',
components: { App }
})