기존에 작성한 코드를 조금 수정해서 Vuex Helpers를 사용해 보겠습니다.
Helpers는 컴포넌트의 computed
나 methods
속성에 Vuex 저장소(Store) 내용을 바인딩하여 좀 더 직관적으로 사용할 수 있게 도와줍니다.
Vuex에서 사용하는 상태(State), 게터(Getters), 변이(Mutations), 액션(Actions)을 맵핑할 수 있습니다.
먼저, FruitsList.vue
를 수정하겠습니다.
<!--FruitsList.vue-->
<!-- ... -->
<script>
import { mapState, mapGetters } from 'vuex';
export default {
computed: {
...mapState([ // ES6 - Spread
'fruits'
]),
...mapGetters([ // ES6 - Spread
'upperCaseFruits'
])
}
}
</script>
<style></style>
상태(State)를 바인딩하기 위해서 mapState
를 사용했고,
게터(Getters)를 위해 mapGetters
를 사용했습니다.
문법적으로 객체의 속성이나 메소드 자리에서는 함수 실행을 할 수 없는데, 함수 앞에 전개 연산자(Spread / ...
)를 사용하면 객체의 일부로 확장해서 사용할 수 있습니다.
Helpers는 이 방식을 사용하여 작성합니다.
우선 문제가 없는지 결과를 확인하세요.
혹시 전개 연산자 때문에 문제가 있다면 ‘Babel Preset’이 필요할 수 있습니다.
$ npm install --save-dev babel-preset-es2015
// .babelrc
{
"presets": ["es2015"]
}
잘 나오는지 확인하셨다면 다음 컴포넌트들도 수정하겠습니다.
<!--FruitsPrice.vue-->
<!-- ... -->
<script>
import { mapState } from 'vuex';
export default {
computed: {
...mapState(['fruits'])
}
}
</script>
<style></style>
BtnDiscount.vue
의 경우 mapActions
를 사용합니다.
기존 코드에서는 dispatch
메소드에 Payload 인자로 할인율을 전달해서 사용했습니다.
discountPrice() {
this.$store.dispatch('discountPrice', {
discountRate: 20
});
}
하지만 mapActions
로 맵핑하면 Payload 인자를 직접 사용할 수 없기 때문에, 별도 데이터를 만들어서 클릭 이벤트가 발생할 때 인자로 사용합니다.
<!--BtnDiscount.vue-->
<template>
<div class="btn" @click="discountPrice(discountData)">DISCOUNT PRICE</div>
</template>
<script>
import { mapActions } from 'vuex';
export default {
data() {
return {
discountData: {
rate: 20
}
}
},
methods: {
...mapActions([
'discountPrice'
])
}
}
</script>
<!-- ... -->
이벤트 발생의 전달 인자로 discountData
라는 객체를 만듭니다.discountData
객체는 rate
속성을 가지는데 저장소(Store)에는 Payload가 discountRate
속성을 사용하도록 작성되어 있습니다.
이름을 수정하겠습니다.
// store.js
// ...
export const store = new Vuex.Store({
state: {
// ...
},
getters: {
// ...
},
mutations: {
discountPrice(state, payload) {
state.fruits.forEach(fruit => {
fruit.price *= (100 - payload.rate) / 100; // discountRate >> rate
});
}
},
actions: {
// ...
}
});
Helpers를 사용해서 모두 수정했습니다.
잘 동작하는지 확인하세요.
혹시 매핑한 이름이 최적화가 아니거나 적당하지 않다면, 다음과 같이 컴포넌트 안에서 맵핑하는 메소드의 이름을 변경해 사용할 수 있습니다.
<!--BtnDiscount.vue-->
<template>
<div class="btn" @click="price(discountData)">DISCOUNT PRICE</div>
</template>
<script>
import { mapActions } from 'vuex';
export default {
data() {
return {
discountData: {
rate: 20
}
}
},
methods: {
...mapActions({
price: 'discountPrice'
})
}
}
</script>
<!-- ... -->