Vuex는 단일 상태 트리(single state tree)를 사용한다.
즉, 이 단일 객체는 모든 애플리케이션의 상태를 포함하며 원본 소스(single source of truth) 역할을 한다.
이는 각 애플리케이션마다 하나의 저장소만 갖게 된다는 것을 의미한다.
단일 상태 트리를 사용하면 특정 상태를 쉽게 찾을 수 있으므로 디버깅을 위해 현재 앱 상태의 스냅샷을 쉽게 가져올 수 있고 단일 상태 트리는 모듈성과 충돌하지 않는다.
Vuex 저장소의 반응적이기 때문에 저장소에서 상태를 검색하는 가장 간단한 방법은
computed
속성 내에서 일부 저장소 상태(ex. store.state.count)를 가져오는 것이다.
// Counter 컴포넌트
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return store.state.count
}
}
}
store.state.count
가 변경되면 computed
속성이 다시 변경되고 관련 DOM 업데이트가 트리거 된다.
그러나 이 패턴은 컴포넌트가 전역 저장소 단독 항목에 의존하게 한다.
Vuex는 store 옵션(Vue.use(Vuex)
에 의해 가능)으로 루트 컴포넌트의 모든 자식 컴포넌트에 저장소를 주입(inject)하는 메커니즘을 제공한다.
const app = new Vue({
el: '#app',
// store 옵션을 사용하여 저장소를 제공하면 모든 하위 컴포넌트에 저장소 인스턴스가 삽입됨
store,
components: { Counter },
template: `
<div class="app">
<counter></counter>
</div>
`
})
루트 인스턴스에 store 옵션을 제공함으로써 저장소는 루트의 모든 하위 컴포넌트에 주입되고 this.$store
로 사용할 수 있다.
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return this.$store.state.count
}
}
}
컴포넌트가 여러 저장소 상태 속성이나 getter를 사용해야 하는 경우,
computed
속성을 모두 선언하면 반복적이고 장황해진다.
이를 처리하기 위해 계산된 getter 함수를 생성하는 mapState 헬퍼를 사용하여 키 입력을 줄일 수 있다.
// 독립 실행 형 빌드에서 헬퍼가 Vuex.mapState로 노출
import { mapState } from 'vuex'
export default {
// ...
computed: mapState({
// 화살표 함수는 코드를 매우 간결하게 만들어줌
count: state => state.count,
// 문자열 값 'count'를 전달하는 것은 `state => state.count`와 같음
countAlias: 'count',
// `this`를 사용하여 로컬 상태에 액세스하려면 일반적인 함수를 사용해야함
countPlusLocalState (state) {
return state.count + this.localCount
}
})
}
또한 매핑 된 계산된 속성의 이름이 상태 하위 트리 이름과 같을 때 문자열 배열을 mapState에 전달할 수 있다.
computed: mapState([
// this.count를 store.state.count에 매핑
'count'
])
mapState는 객체를 반환한다.
다른 로컬 영역의 계산된 속성과 함께 사용하려면
일반적으로, 최종 객체를 computed
에 전달할 수 있도록 여러 객체를 하나로 병합하는 유틸리티를 사용해야 한다.
그러나 객체 전개 연산자(Object Spread Operator)를 사용하면 문법을 매우 단순화 할 수 있다.
computed: {
localComputed () { /* ... */ },
// 객체 전개 연산자(Object Spread Operator)를 사용하여 외부 객체에 추가
...mapState({
// ...
})
}
Vuex를 사용한다고 해서 Vuex에 모든 상태를 넣어야하는 것은 아니다.
Vuex에 더 많은 상태를 넣으면 상태 변이가 더 명확하고 디버그 가능하지만,
때로는 코드를 보다 장황해지게 한다.
기회비용에 맞게 판단하고 앱의 개발 요구에 맞는 결정을 내려야 하며,
상태들이 단일 컴포넌트에만 속한 경우(사용되는 경우) 로컬 상태로 남겨두어야 한다.