Vuex mutations

1 개요[ | ]

Vuex mutations
Vuex 변이
  • Vuex 저장소에서 실제로 상태를 변경하는 유일한 방법은 변이하는 것이다.
  • Vuex 변이는 이벤트와 매우 유사하다.

2 예제 1 - 단순 커밋[ | ]

  • 핸들러 함수는 실제 상태(state)를 수정하는 곳이며, 첫 번째 전달인자로 상태(state)를 받는다.
  • 변이 핸들러는 직접 호출할 수 없는데, 이벤트를 등록하는 것과 비슷하다.
  • "타입이 increment인 변이가 발생하면 그 핸들러를 호출한다."
  • 변이 핸들러를 호출하려면, 해당 type('increment')과 함께 store.commit을 호출해야 한다.
<div id="app">
  <span>{{ count }}</span>
  <button @click="increment">+</button>
</div>

<script src="//unpkg.com/vue/dist/vue.min.js"></script>
<script src="//unpkg.com/vuex/dist/vuex.min.js"></script>
<script>
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      // 상태 변이
      state.count++
    }
  }
})

new Vue({
  el: '#app',
  computed: {
    count() {
      return store.state.count
    }
  },
  methods: {
    increment() {
      store.commit('increment')
    }
  }
})
</script>

3 예제 2 - 페이로드를 가진 커밋 1[ | ]

  • store.commit에 payload 라고 하는 추가 전달인자를 사용할 수 있다.
<div id="app">
  <span>{{ count }}</span>
  <button @click="increment1">+1</button>
  <button @click="increment10">+10</button>
</div>

<script src="//unpkg.com/vue/dist/vue.min.js"></script>
<script src="//unpkg.com/vuex/dist/vuex.min.js"></script>
<script>
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state, n) {
      state.count += n
    }
  }
})

new Vue({
  el: '#app',
  computed: {
    count() {
      return store.state.count
    }
  },
  methods: {
    increment1() {
      store.commit('increment', 1)
    },
    increment10() {
      store.commit('increment', 10)
    }
  }
})
</script>

4 예제 3 - 페이로드를 가진 커밋 2[ | ]

  • 대부분의 경우, payload는 여러 필드를 가질 수 있는 객체여야 한다.
<div id="app">
  <span>{{ count }}</span>
  <button @click="increment1">+1</button>
  <button @click="increment10">+10</button>
</div>

<script src="//unpkg.com/vue/dist/vue.min.js"></script>
<script src="//unpkg.com/vuex/dist/vuex.min.js"></script>
<script>
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state, payload) {
      state.count += payload.amount
    }
  }
})

new Vue({
  el: '#app',
  computed: {
    count() {
      return store.state.count
    }
  },
  methods: {
    increment1() {
      store.commit('increment', {
        amount: 1
      })
    },
    increment10() {
      store.commit('increment', {
        amount: 10
      })
    }
  }
})
</script>

5 예제 4 - 객체 스타일 커밋[ | ]

  • 변이를 커밋하는 또 다른 방법은 type 속성을 가진 객체를 직접 사용하는 것이다.
<div id="app">
  <span>{{ count }}</span>
  <button @click="increment1">+1</button>
  <button @click="increment10">+10</button>
</div>

<script src="//unpkg.com/vue/dist/vue.min.js"></script>
<script src="//unpkg.com/vuex/dist/vuex.min.js"></script>
<script>
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state, payload) {
      state.count += payload.amount
    }
  }
})

new Vue({
  el: '#app',
  computed: {
    count() {
      return store.state.count
    }
  },
  methods: {
    increment1() {
      store.commit({
        type: 'increment',
        amount: 1
      })
    },
    increment10() {
      store.commit({
        type: 'increment',
        amount: 10
      })
    }
  }
})
</script>

6 Vue의 반응성 규칙을 따르는 변이[ | ]

  • Vuex 저장소의 상태는 Vue에 의해 반응하므로, 상태를 변경하면 상태를 관찰하는 Vue 컴포넌트가 자동으로 업데이트된다.
  • 이것은 Vuex 변이가 일반 Vue로 작업할 때와 동일하게 반응성 경고를 받을 수 있음을 의미한다.
  • 저장소에서 모든 필드를 미리 초기화해두는 것이 좋다.
  • 새로운 속성을 추가하려면 다음 중 하나로 해야 한다.
// 일반 문법
Vue.set(obj, 'newProp', 123)
// 객체 확산 문법 (객체가 교체된다.)
state.obj = { ...state.obj, newProp: 123 }

7 변이 타입에 상수 사용[ | ]

  • 다양한 Flux 구현에서 변이 유형에 상수를 사용하는 것은 일반적인 패턴이다.
  • 이를 통해 코드에 linter 등의 도구를 사용할 수 있으며, 모든 상수를 하나의 파일에 저장하면 전체 애플리케이션에서 어떤 변이를 쓸 수 있는지를 한눈에 파악할 수 있다.
// 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의 computed 프로퍼티명 기능을 이용하여
    // 함수명으로 상수를 사용할 수 있다
    [SOME_MUTATION] (state) {
      // 상태 변이 
    }
  }
})
  • 상수를 사용하는 것이 필수는 아니다. 개발자가 많은 대규모 프로젝트에서 유용할 수 있지만, 선택사항이다.

8 변이는 반드시 동기적이어야 한다[ | ]

  • 한 가지 중요한 규칙은 변이 핸들러 함수는 동기적이어야 한다는 것이다.
  • 왜 그럴까? 다음 예제를 통해 확인해보자.
mutations: {
  someMutation (state) {
    api.callAsyncMethod(() => {
      state.count++
    })
  }
}
  • 앱을 디버깅하고 devtool의 변이 로그를 보고 있다고 생각해보자.
  • 기록된 모든 변이에 대해 devtool은 상태의 "이전"과 "이후" 스냅샷을 캡처해야 한다.
  • 그러나 위의 예제에서 변이 내의 비동기 콜백은 불가능하다.
  • 변이가 커밋되었을 때 콜백은 아직 호출되지 않으며, 콜백이 실제로 호출될 시기를 devtool이 알 수 있는 방법이 없다.
  • 콜백에서 수행된 모든 상태 변이는 본질적으로 추적할 수 없다!

9 참고[ | ]

문서 댓글 ({{ doc_comments.length }})
{{ comment.name }} {{ comment.created | snstime }}