보통 이제 프론트엔드 공부를 하다보면
초반에 emit props등을 통해서 컴포넌트간에 데이터 전달을 배운다
뭐 자식컴포넌트에서 부모컴포넌트로는 어떻게 보내고 반대로는 어떻게 보내고 어쩌고~~
근데 컴포넌트 중첩이 너무 깊어지면 데이터 전달도 쉽지않고 유지보수에도 어려움이 생길 수 있다.
그래서 오늘은 뷰에서 가장 많이 사용하는?(사실 나는 뷰엑스밖에 안써봄 ㅋㅋㅋ) 상태관리 라이브러리인
vuex에 대해 알아보자
vue2 문법으로 작성하려 했으나 요즘은 vue3많이 쓰니까 vue3 기준으로 작성해 보겠따
그리고 나는
여기를 정말 많이 참고했따
vuex
- "state management pattern + Library" for vue.js (상태 관리 패턴 + 라이브러리)
- 중앙 저장소를 통해 상태 관리를 할 수 있도록 하는 라이브러리
- 데이터가 예측 가능한 방식으로만 변경 될 수 있도록하는 규칙을 설정하며, Vue의 반응성을 효율적으로 사용하는 상태 관리 기능을 제공
- Vue의 공식 도구로써 다양한 기능을 제공
시작하기
- $ vue create vuex-app => vue 프로젝트 생성
- $ cd vuex-app => 이동
- $ vue add vuex => Vue CLI를 통해 vuex plugin 적용
state
- vue 인스턴스의 data에 해당
- 중앙에서 관리하는 모든 상태 정보
- 개별 component는 state에서 데이터를 가져와서 사용
- 개별 component가 관리하던 data를 중앙 저장소에서 관리하게 됨
- state의 데이터가 변화하면 해당 데이터를 사용(공유)하는 component도 자동으로 다시 렌더링
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
message: 'message in store'
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
}
})
- component에서 state 사용
// App.vue
<template>
<div id="app">
<h1>{{ message }}</h1>
</div>
</template>
<script>
import { computed } from "vue";
import { useStore } from "vuex";
export default {
setup() {
const store = useStore();
const message = computed(() => store.state.message);
return { message };
}
};
</script>
action
- state를 변경할 수 있는 mutations 호출
- component에서 dispatch()에 의해 호출됨
- dispatch(A, B)
- A:호출하고자 하는 actions 함수
- B:넘겨주는 데이터(payload)
- actions에 정의된 changeMessage 함수에 데이터 전달하기
- component에서 actions는 dispatch()에 의해 호출됨
// store/index.js
export default new Vuex.Store({
...
actions: {
changeMessge(context, message) {
console.log(context)
console.log(message)
},
},
})
- 사용
// App.vue
<template>
<div id="app">
<h1>{{ message }}</h1>
</div>
</template>
<script>
import { computed } from "vue";
import { useStore } from "vuex";
export default {
setup() {
const store = useStore();
const message = computed(() => store.state.message);
const newMessage = "가라아아아"
const doAction = () => {
store.dispatch('changeMessage', newMessage)
}
return { message, doAction };
}
};
</script>
mutaion
- mutations는 state를 변경하는 유일한 방법
- component 또는 actions에서 commit()에 의해 호출됨
- commit(A, B)
- A: 호출하고자 하는 mutations 함수
- B: payload
- mutations 함수의
- 첫 번째 인자는 state
- 두 번째 인자는 payload
// stor/index.js
...
mutations: {
CHANGE_MESSAGE(state, newMessage){
console.log(state)
console.log(newMessage)
state.message = newMessage
},
},
actions: {
changeMessage(context, newMessage) {
// console.log(context)
// console.log(message)
context.commit('CHANGE_MESSAGE', newMessage)
},
},
getters
- getters는 state를 활용한 새로운 변수
// store/index.js
...
getters: {
messageLength(state) {
return state.message.length
},
},
// App.vue
<template>
<div id="app">
<h1>{{ message }}</h1>
<h2>{{test.messageLength}}</h2>
</div>
</template>
<script>
import { computed } from "vue";
import { useStore } from "vuex";
export default {
setup() {
const store = useStore();
const message = computed(() => store.state.message);
const test = computed(() => store.getters);
return { message, test };
}
};
</script>
이렇게 일단 뷰엑스에 필수적인 요소들을 정리해 보았따
하지만 store도 다른 컴포넌트나 css파일들과 비슷하게 폴더를 분리해서 관리하는게 유지보수에도 좋다
그래서 store를 모듈화 하는 방법에 대해 알아보자
모듈화
- store/modules에 여러 모듈 스토어들을 만들고 가장 상단에 있는 index.js에 모듈을 추가해준다
// store/modules/moduel_A
export const module_A = {
state: () => ({}),
mutations: {},
getters: {},
actions: {},
}
// store/modules/moduel_B
export const module_B = {
state: () => ({}),
mutations: {},
getters: {},
actions: {},
}
// store/index.js
import { createStore } from "vuex";
import { module_A } from "./modules/module_A";
import { module_B } from "./modules/module_B";
export default createStore({
modules: { module_A, module_B}})
이런식으로 하면 되는데
모듈화를 하면 당연하게도 컴포넌트에서 스토어 값들을 불러올때도 방법이 약간 달라진다
state는 state.moduleName.stateName으로 부르고
getter와 mutation, action은 moduleName으로 쪼개서 들어가지 않고 전역 값으로 들어간다
<script>
import { computed, ref } from "vue";
import { useStore } from "vuex";
export default {
name: "MovieMain",
setup() {
const store = useStore()
// mutation 부르기
const goHome = () => {
store.commit("CHANGE_NOWSTATE", "home")
}
// action 부르기
const axiosTest = () => {
store.dispatch("axios_test")
movie_toggle.value = !movie_toggle.value
}
// state 부르기
const movies = computed(() => store.state.module_A.movies)
return { goHome,axiosTest,movies }
},
};
</script>
하지만 여기서 또 문제가 발생할 수 있다.
getter와 mutation, action은 전역으로 들어가니까 컴포넌트에서 사용할 때 이놈이 어느 스토어에서 온놈인지 헷갈릴 수 있지 않겠는가?
그래서 해결 방법은 namespace로 스토어를 관리하는 것이다.
사용방법은 module에 namespaced: true 만 넣어주면 된다
// store/modules/moduel_A
export const module_A = {
namespaced: true,
state: () => ({}),
mutations: {},
getters: {},
actions: {},
}
이렇게 하면 컴포넌트에서 불러오는 방법이 약간 달라진다 .
state는 기존대로 state.moduleName.stateName으로 부른다.
getters는 computed(() => store.getters["moduleName/getterName"])으로 부른다.
mutation은 store.commit("moduleName/mutationName", params)으로 부른다.
action은 store.dispatch("moduleName/actionName", params)으로 부른다.
이렇게 vuex에 대해 알아봤따
아마 vue로 프로젝트를 하면서 vuex를 안쓰는 프로젝트는 거의 없을거다
그만큼 vuex는 중요하니까 열심히 공부해서 잘 써보시길 바란다
'개발💻 > Vue' 카테고리의 다른 글
[Vue] Vue 정리하기(5) - Vue3 composition api 1편 (0) | 2023.09.18 |
---|---|
[Vue] Vue 정리하기(4) - Vue Router (0) | 2023.09.15 |
[Vue] Vue 정리하기(2) - Vue Directive (0) | 2023.09.14 |
[Vue] Vue 정리하기(1) - Vue CLI, Component (0) | 2023.09.14 |
[Vue] Vue 정리하기(0) - 뷰를 시작하기 앞서 (2) | 2023.09.13 |