Vuex 저장소에서 실제로 상태를 변경하는 유일한 방법은 변이(mutations)하는 것이다.
Vuex mutations은 이벤트와 매우 유사하다.
각 mutations에는 타입 문자열 핸들러가 있고 핸들러 함수는 실제 상태 수정을 하는 곳이며, 첫 번째 전달인자로 상태를 받는다.
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 상태 변이
state.count++
}
}
})
mutations 핸들러를 직접 호출 할 수는 없다.
위 예제에서 타입이 increment인 mutations이 발생하면이 핸들러를 호출한다.
mutations 핸들러를 호출하려면 해당 타입과 함께 store.commit
을 호출해야 한다.
store.commit('increment')
mutations에 대해 payload 라고하는 store.commit
에 추가 전달인자를 사용 할 수 있다.
// ...
mutations: {
increment (state, n) {
state.count += n
}
}
store.commit('increment', 10)
payload는 객체로 전달될 수 도 있다.
// ...
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
store.commit('increment', {
amount: 10
})
mutations을 commit하는 또 다른 방법은 type 속성을 가진 객체를 직접 사용하는 것이다.
store.commit({
type: 'increment',
amount: 10
})
객체 스타일 commit을 사용할 때 전체 객체는 mutations 핸들러에 페이로드로 전달되므로 핸들러는 동일하게 유지된다.
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
Vuex 저장소의 상태는 Vue에 의해 반응하므로, 상태를 변경하면 상태를 관찰하는 Vue 컴포넌트가 자동으로 업데이트된다.
이것은 Vuex mutations이 일반 Vue로 작업 할 때 동일한 반응성에 대한 경고를 받을 수 있음을 의미한다.
Vue.set(obj, 'newProp', 123)
을 사용하거나,state.obj = { ...state.obj, newProp: 123 }
다양한 Flux 구현에서 mutations 유형에 상수를 사용하는 것은 일반인 패턴이다.
상수를 사용하는 것은 개발자가 많은 대규모 프로젝트에서 유용할 수 있지만,
이는 완전한 선택 사항이다.
// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'
const store = new Vuex.Store({
state: { ... },
mutations: {
// ES2015에서 계산 된 프로퍼티 이름 기능을 사용하여
// 상수를 함수 이름으로 사용할 수 있음
[SOME_MUTATION] (state) {
// 변이 상태
}
}
})
this.$store.commit('xxx')
를 사용하여 컴포넌트에서 mutations를 수행하거나 컴포넌트 메소드를 store.commit
호출에 매핑하는 mapMutations 헬퍼를 사용할 수 있다.
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment' // this.increment()를 this.$store.commit('increment')에 매핑합니다.
]),
...mapMutations({
add: 'increment' // this.add()를 this.$store.commit('increment')에 매핑합니다.
})
}
}
기억 해야할 한 가지 중요한 규칙은 mutations 핸들러 함수는 동기적이어야 한다는 것이다.
mutations: {
someMutation (state) {
api.callAsyncMethod(() => {
state.count++
})
}
}
기록된 모든 mutations에 대해 devtool은 상태의 이전∙이후 스냅샷을 캡처해야 한다.
그러나 위 mutations 내의 비동기 콜백은 불가능하다.
mutations이 commit 되었을 때 콜백은 아직 호출되지 않고, 콜백이 실제로 호출 될 시기를 devtool이 알 수 있는 방법이 없다.
콜백에서 수행 된 모든 상태 mutations은 본질적으로 추적 할 수 없다.
이를 해결하기 위해서는 액션을 사용해야 한다.