front-end/Vue.js
Vuex 기초배우기 #4 (mapState, mapGetters)
정구
2022. 2. 22. 10:23
728x90
mapState와 mapGetters는 state, getters를 보다 쉽게 사용할 수 있게 도와준다
앞의 코드에서 좀 더 복잡한 계산을 getters에 작성해보겠다.
전체 유저에서 서울에 살고 있는 사람의 수와 그 퍼센트를 계산해준다.
src/store.js
getters: {
allUsersCount: (state) => {
return state.allUsers.length;
},
countOfSeoul: (state) => {
let count = 0;
state.allUsers.forEach((user) => {
if (user.address === "Seoul") count++;
});
return count;
},
percentOfSeoul: (state, getters) => {
return Math.round((getters.countOfSeoul / getters.allUsersCount) * 100);
},
},
percentOfSeoul에서 getters만 인자로 받으면 될 것 같지만
countOfSeoul과 allUsersCount의 값은 state를 인자로 받아 만들어졌기 때문에
state도 꼭 인자로 넣어준다.
countOfSeoul과 percentOfSeoul을 컴포넌트에서 사용해준다.
src/components/Users/AllUsers.vue
<template>
<div>
<h1>All Users({{ $store.getters.allUsersCount }})</h1>
<h3>
Seoul Users: {{ $store.getters.countOfSeoul }}({{$store.getters.percentOfSeoul}}%)
</h3>
<v-list two-line>
<v-list-tile
v-for="(user, index) in $store.state.allUsers"
:key="index"
avatar
>
<v-list-tile-avatar color="grey lighten-3">
<img :src="user.src" />
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title v-html="user.name"></v-list-tile-title>
<v-list-tile-sub-title
>id:#{{ index }} / {{ user.address }} 거주</v-list-tile-sub-title
>
</v-list-tile-content>
</v-list-tile>
</v-list>
</div>
</template>
$store.getters에 계속 접근해야 하는, 반복적인 코드를 사용해야 하는 불편함이 생긴다.
이때 사용할 수 있는 것이 바로 mapGetters이다.
vuex에서 제공하는 기능으로 컴포넌트에서 getters에 바로 접근할 수 있게 만들어준다.
src/components/Users/AllUsers.vue
<template>
<div>
<h1>All Users({{ allUsersCount }})</h1>
<h3>Seoul Users: {{ countOfSeoul }}({{ percentOfSeoul }}%)</h3>
<v-list two-line>
<v-list-tile
v-for="(user, index) in $store.state.allUsers"
:key="index"
avatar
>
<v-list-tile-avatar color="grey lighten-3">
<img :src="user.src" />
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title v-html="user.name"></v-list-tile-title>
<v-list-tile-sub-title
>id:#{{ index }} / {{ user.address }} 거주</v-list-tile-sub-title
>
</v-list-tile-content>
</v-list-tile>
</v-list>
</div>
</template>
<script>
import { EventBus } from "@/main.js";
import { mapGetters } from "vuex";
export default {
data() {
return {};
},
computed: {
...mapGetters(["allUsersCount", "countOfSeoul", "percentOfSeoul"]),
},
mounted() {
EventBus.$on("signUp", (users) => {
this.$store.state.allUsers.push(users);
});
},
};
</script>
mapGetters를 객체로 import해주고 (이때 vuex에서 제공해주는 기능이기에 from 'vuex'로 적어야 한다.
computed에... mapGetters( [ ' ' ] ) 형식으로 getters에서 가져올 데이터를 선언해준다.
template에서는 $store.getters를 지우고 이름만 가지고 사용할 수 있다.
만약 getters에서 가져온 값들을 현재 컴포넌트에서 다른 이름으로 사용하고자 하면 배열이 아닌 객체 형식으로 선언해 주면 된다.
computed: {
...mapGetters({
count: 'allUsersCount',
seouls: 'countOfSeoul',
percent: 'percentOfSeoul'
})
}
state 또한 mapGetter처럼 mapState를 사용할 수 있다.
src/components/Users/AllUsers.vue
<template>
<div>
<h1>All Users({{ count }})</h1>
<h3>Seoul Users: {{ seouls }}({{ percent }}%)</h3>
<v-list two-line>
<v-list-tile v-for="(user, index) in allUsers" :key="index" avatar>
<v-list-tile-avatar color="grey lighten-3">
<img :src="user.src" />
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title v-html="user.name"></v-list-tile-title>
<v-list-tile-sub-title>
id:#{{ index }} / {{ user.address }} 거주
</v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</div>
</template>
<script>
import { EventBus } from "@/main.js";
import { mapState, mapGetters } from "vuex";
export default {
data() {
return {};
},
computed: {
...mapGetters({
count: "allUsersCount",
seouls: "countOfSeoul",
percent: "percentOfSeoul",
}),
...mapState(["allUsers"]),
},
mounted() {
EventBus.$on("signUp", (users) => {
this.allUsers.push(users);
});
},
};
</script>
mapState와 mapGetters를 통해 정리된 모습
훨씬 가독성이 좋아지고 깔끔해졌다.
728x90