Vuex는 Vue.js app에 대한 상태관리패턴 + 라이브러리이다.
Vuex를 사용하면 컴포넌트 간 통신을 아래와 같이 수행할 수 있다.
Vue의 핵심 구성요소는 아래와 같다.
Actions의 의미는 아래와 같다.
Mutations의 의미는 아래와 같다.
State의 의미는 아래와 같다.
State가 변했을 때 출력되는 화면을 변하게 하기 위해서 Getters를 쓴다.
Getters의 의미는 아래와 같다.
원래는 아래와 같이 컴포넌트 통신을 해야 한다.
// Step00View.vue
<template>
<div class="text-center">
<h2>당신이 좋아하는 파트를 선택하세요</h2>
<result-component :total="count" />
<subject-component @add-tot-count="addTotalCount" title="코딩"></subject-component>
<subject-component @add-tot-count="addTotalCount" title="알고리즘"></subject-component>
</div>
</template>
<script>
import ResultComponent from "@/components/step00/ResultComponent";
import SubjectComponent from "@/components/step00/SubjectComponent";
export default {
data() {
return {
count: 0,
};
},
components: {
ResultComponent,
SubjectComponent,
},
methods: {
addTotalCount() {
this.count += 1;
},
},
};
</script>
<style scoped>
.text-center {
text-align: center;
}
</style>
// ResultComponent.vue
<template>
<h2>{{ total }}</h2>
</template>
<script>
export default {
// props: ["total"],
computed: {
total() {
return this.$store.state.count;
},
},
};
</script>
<style></style>
// SubjectComponent.vue
<template>
<button @click="addCount">{{ title }} - {{ count }}</button>
</template>
<script>
export default {
name: "SubjectComponent",
props: ["title"],
data() {
return {
count: 0,
};
},
methods: {
addCount: function () {
this.count += 1;
// this.$emit("addtotcount");
this.$store.state.count++;
},
},
};
</script>
<style></style>
하지만 Vuex를 쓰면 아래와 같이 컴포넌트 통신을 할 수 있다.
// store/index.js
export default new Vuex.Store({
state: {
count: 0,
},
actions: {
asyncAddOne(context) { // 첫번째 인자로 context가 자동 주입
setTimeout(() => {
context.commit("addOne");
}, 2000);
},
},
mutations: {
ADD_ONE(state) { // 첫번째 인자로 state가 자동 주입
state.count += 1;
},
ADD_TEN_COUNT(state, payload) {
state.count += payload;
},
ADD_OBJ_COUNT(state, payload) {
state.count += payload.num;
},
},
getters: {
// 복잡한 계산식을 처리 : computed
countMsg(state) { // 첫번째 인자로 state가 자동 주입
let msg = "10번보다 ";
if (state.count > 10) {
msg += "많이 ";
} else {
msg += "적게 ";
}
return msg + " 호출됨(" + state.count + ")";
},
},
});
// Step07View.vue
<template>
<div class="text-center">
<h2>당신이 좋아하는 파트를 선택하세요</h2>
<result-component />
<subject-component title="코딩"></subject-component>
<subject-component title="알고리즘"></subject-component>
</div>
</template>
<script>
import ResultComponent from "@/components/step07/ResultComponent";
import SubjectComponent from "@/components/step07/SubjectComponent";
export default {
components: {
ResultComponent,
SubjectComponent,
},
};
</script>
<style>
.text-center {
text-align: center;
}
</style>
// ResultComponent.vue
<template>
<div>
<h2>{{ total }}</h2>
<h2>{{ countMsg }}</h2>
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
computed: {
// countMsg() {
// return this.$store.getters.countMsg;
// },
...mapGetters(["countMsg"]),
total() {
return this.$store.state.count;
},
},
};
</script>
<style></style>
// SubjectComponent.vue
<template>
<div>
<button @click="addCount">{{ title }} - {{ count }}</button>
<button @click="addTenCount">{{ title }} - {{ count }}</button>
<button @click="addObjCount">{{ title }} - {{ count }}</button>
<button @click="asyncCount">Action {{ title }} - {{ count }}</button>
</div>
</template>
<script>
import { mapMutations, mapActions } from "vuex";
export default {
name: "SubjectComponent",
props: ["title"],
data() {
return {
count: 0,
};
},
methods: {
...mapMutations({
addMOne: "ADD_ONE",
addMTenCount: "ADD_TEN_COUNT",
addMObjCount: "ADD_OBJ_COUNT",
}),
...mapActions(["asyncAddOne"]),
addCount: function () {
this.count += 1;
// this.$store.commit('addOne');
this.addMOne();
},
addTenCount: function () {
this.count += 10;
// this.$store.commit('addCount', 10);
this.addMTenCount(10);
},
addObjCount: function () {
let num = Math.round(Math.random() * 100);
this.count += num;
// this.$store.commit('addObjCount', { num });
this.addMObjCount({ num });
},
asyncCount() {
// this.$store.dispatch("asyncAddOne");
this.asyncAddOne();
},
},
};
</script>
<style></style>