Vuex Binding Helper
- Vuex store의 state, mutations, actions 등을 간단하게 사용할 수 있도록 만들어진 헬퍼 함수
- mapState, mapActions 와 같은 형식으로 사용
- 사용하기 위해서는 import 받아와야 함
import { mapState, mapActions } from 'vuex'
mapState
- Vuex store의 상태를 컴포넌트의 데이터에 매핑할 때 사용
- 객체 혹은 배열 형태로 상태를 매핑하여 사용 할 수 있음
객체 형태로 매핑
- mapState를 import
- Spread operator를 사용하여 mapState를 전개
- mapState 내부에 불러오고자 하는 값을 정의
- 화살표 함수를 사용하여 message key에 state의 message 값을 할당
- key 값은 컴포넌트에서 사용하고자 하는 다른 이름으로 변경하여 사용 할 수 있음
<template>
<div id="app">
<h1>{{ message }}</h1>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
...
...mapState({
msg: state => state.message
}),
},
},
}
</script>
배열 형태로 매핑
- mapState를 import
- Spread operator를 사용하여 mapState를 전개
- vuex store의 상태 중, 불러오고자 하는 대상을 배열의 원소로 정의
<template>
<div id="app">
<h1>{{ message }}</h1>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
...
...mapState(['message']),
},
},
}
</script>
mapActions
- 컴포넌트에서 this.$store.dispatch() 를 호출하는 대신, 액션 메서드를 직접 호출하여 사용 할 수 있음
- mapState와 같이 객체 혹은 배열 형태로 매핑가능
배열 형태로 매핑
- mapState와 동일한 형식으로 사용
- 단, 이 경우 changeMessage에 넘겨주어야 할 inputData를 changeMessage 호출 시 인자로 직접 값을 넘겨주어야 함
<template>
<div id="app">
<h1>{{ message }}</h1>
<input
type="text"
@keyup.enter="changeMessage(inputData)"
v-model="inputData“>
</div>
</template>
<script>
import { mapActions } from 'vuex’
export default {
**...**
methods: {
...mapActions(['changeMessage'])
},
}
</script>
- 정상 작동하지만 input 제출 후 초기화 되지 않음
객체 형태로 매핑
- Actions의 changeMessage를 actionsChangeMessage에 매핑
- this.actionsChangeMessage 형식으로 사용
- payload를 넘겨주거나 추가적인 로직 작성 가능
<template>
<div id="app">
<input
type="text“
@keyup.enter="onSubmit"
v-model="inputData“>
</div>
</template>
<script>
import { mapActions } from 'vuex'
export default {
...
methods: {
...mapActions({
actionsChangeMessage: 'changeMessage'
}),
onSubmit() {
const newMessage = this.inputData
this.actionsChangeMessage(newMessage)
this.inputData = ''
}
}
}
</script>
mapGetters
- mapState, mapActions와 동일한 방식으로 사용가능
<template>
<div id="app">
<h1>길이 {{ messageLength }}의 메시지 {{ message }}를 입력받음</h1>
<h3>x2 : {{ doubleLength }}</h3>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
...
computed: {
...mapGetters(['messageLength', 'doubleLength'])
},
}
</script>
[참고]
- 상황에 따라서는 배열과 객체 형태로 각각 매핑하여 사용 할 수 있음
<template>
<div id="app">
<h1>{{ age }} {{ message }}</h1>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
...
computed: {
...mapState(['message']),
...mapState({
age: state => state.age
})
},
}
</script>
modules
- Vuex store를 여러 파일로 나눠서 관리 할 수 있게 해 주는 기능
- Vuex store와 동일한 구성을 가진 별도의 객체를 정의하여 modules 옵션에 작성한 객체를 추가하여 사용
- 별개의 .js 파일에 정의하고 import 하는 방식으로도 사용가능
- Store의 가독성을 향상시킬 수 있음
Vuex에 적용하기
const myModule = {
state: {
age: 30
},
mutations: {
INCREMENT_AGE(state) {
state.age += 1
}
},
actions: {
incrementAge(context) {
context.commit('INCREMENT_AGE')
}
}
}
export default myModule
- 만약 모듈안의 Vuex 인스턴스를 각각 정의할 경우, export 할 때 반드시 중괄호와 함께 적어주어야 한다.
const state = {
}
const getters = {
}
const mutations = {
}
const actions = {
}
export default {
state,
getters,
mutations,
actions,
}
import Vue from 'vue'
import Vuex from 'vuex'
import myModule from './modules/myModule'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
myModule
}
})
- 클릭하면 age가 올라가게 하는 버튼 작성하기
<template>
<div id="app">
<h1>길이 {{ messageLength }}의 메시지 {{ message }}를 입력받음</h1>
<h3>x2 : {{ doubleLength }}</h3>
<input type="text" @keyup.enter="onSubmit" v-model="inputData">
<h1>{{ age }}</h1>
<button @click="upage">age up</button>
</div>
</template>
<script>
import { mapState, mapActions, mapGetters } from 'vuex'
export default {
name: 'App',
components: {
},
created() {
this.$store.dispatch('loadMessage')
},
computed: {
...mapState({
msg: state => state.message,
age: state => state.myModule.age,
}),
...mapGetters(['messageLength', 'doubleLength'])
},
data() {
return {
inputData: null,
}
},
methods: {
...mapActions({
actionsChangeMessage: 'changeMessage',
}),
onSubmit() {
const newMessage = this.inputData
this.actionsChangeMessage(newMessage)
this.inputData = null
},
upage() {
this.$store.dispatch('incrementAge')
}
},
}
</script>
<template>
<div id="app">
<h1>길이 {{ messageLength }}의 메시지 {{ message }}를 입력받음</h1>
<h3>x2 : {{ doubleLength }}</h3>
<!-- mapActions 배열 형태로 매핑 -->
<!-- <input type="text" @keyup.enter="changeMessage(inputData)" v-model="inputData"> -->
<!-- mapActions 객체 형태로 매핑 -->
<input type="text" @keyup.enter="onSubmit" v-model="inputData">
<h1>{{ age }}</h1>
<button @click="upage">age up</button>
</div>
</template>
<script>
import { mapState, mapActions, mapGetters } from 'vuex'
export default {
name: 'App',
components: {
},
created() {
this.$store.dispatch('loadMessage')
},
computed: {
...mapState({
msg: state => state.message,
age: state => state.myModule.age,
}),
...mapGetters(['messageLength', 'doubleLength'])
},
data() {
return {
inputData: null,
}
},
methods: {
...mapActions({
actionsChangeMessage: 'changeMessage',
upage: 'incrementAge'
}),
onSubmit() {
const newMessage = this.inputData
this.actionsChangeMessage(newMessage)
this.inputData = null
},
},
}
</script>