Vue.js 3.0
[Vue.js 3.0] vuex (3)
프갭
2023. 3. 21. 15:14
vuex 는 Vue.js애플리케이션에 대한 상태 관리 패턴 + 라이브러리 입니다.
모든 컴포넌트에 대한 중앙 집중식 저장소 역할
1) 설치 및 설정
https://eehnuyh.tistory.com/8 환경 설정을 Manually select features으로 진행 했을시 설치 항목은 넘어가도 됩니다.
1. PS D:\831228 EEH\EEH\EX\VUE\exui> npm i -save vuex
2. 폴더 및 store 파일 생성 (index.ts or index.js)
3.main.ts,main.js에 사용 선언
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
createApp(App).use(store).use(router).mount('#app');
2) src/store/index.ts (Vuex 기본 구조)
import { createStore } from 'vuex';
export default createStore({
state: {},
getters: {},
mutations: {},
actions: {},
modules: {},
});
(1) state : 컴포넌트 간의 공유할 Data 속성
index.ts
import { createStore } from 'vuex';
export default createStore({
state: {
count: 0,
},
getters: {},
mutations: {},
actions: {},
modules: {},
});
<template>
<div>count:{{ store.state.count }}</div>
</template>
<script lang="ts" setup>
import { useStore } from 'vuex';
const store = useStore();
</script>
(2) getters : 연산된 state값을 접근하는 속성
중앙 데이터 관리 구조에서 발생하는 문제중 하나는 각 컴포넌트에서 vuex 데이터 접근 할때 중복된 코드를 하게되는데 그런 비효율적인 코드를 vuex에 구현하여 가독성을 올리는 이점을 갖게 해준다.
index.ts
import { createStore } from 'vuex';
export default createStore({
state: {
count: 0,
},
getters: {
getStringCount(state) {
return '현재 카운트 값은 ' + state.count + '입니다.';
},
},
mutations: {},
actions: {},
modules: {},
});

<template>
<div>count:{{ store.state.count }}</div>
<div>string count:{{ store.getters.getStringCount }}</div>
</template>
<script lang="ts" setup>
import { useStore } from 'vuex';
const store = useStore();
</script>

state는 직접 변경할 수 없습니다. 그래서 핸들러 함수를 통해서 state를 변경해야 합니다. 즉, setter로 생각하시면 됩니다.
(commit 으로 호출 가능)
index.ts
import { createStore } from 'vuex';
export default createStore({
state: {
count: 0,
},
getters: {
getStringCount(state) {
return '현재 카운트 값은 ' + state.count + '입니다.';
},
},
mutations: {
setCount(state, val) {
state.count = state.count + val;
},
},
actions: {},
modules: {},
});
VuexView.vue
<template>
<div>count:{{ store.state.count }}</div>
<div>string count:{{ store.getters.getStringCount }}</div>
<input type="button" value="Add" @click="TestMutations" />
</template>
<script lang="ts" setup>
import { useStore } from 'vuex';
const store = useStore();
const TestMutations = () => {
store.commit('setCount', 1);
};
</script>

(4) actions : mutations 에는 순차적인 로직(동기 방식) actions은 비순차적인 로직(비동기 방식)에 사용 된다.
mutations 는 state 값의 변화를 추적하기 어렵지만,actions는 변경 확인이 쉬어 비동기 방식에 사용된다.
(dispatch 으로 호출 가능)
index.ts
import { createStore } from 'vuex';
export default createStore({
state: {
count: 0,
},
getters: {
getStringCount(state) {
return '현재 카운트 값은 ' + state.count + '입니다.';
},
},
mutations: {
setCount(state, val) {
state.count = state.count + val;
},
},
actions: {
setCountAsync(context, val) {
setTimeout(() => {
context.commit('setCount', val);
}, 3000);
},
},
modules: {},
});
VuexView.vue
<template>
<div>count:{{ store.state.count }}</div>
<div>string count:{{ store.getters.getStringCount }}</div>
<input type="button" value="Add" @click="TestMutations" />
</template>
<script lang="ts" setup>
import { useStore } from 'vuex';
const store = useStore();
const TestMutations = () => {
store.commit('setCount', 1);
store.dispatch('setCountAsync', 1);
};
</script>
(5) modules : 규모가 큰 프로젝트인경우 사용되는 속성이나 상태 메서드가 많아진다 그럴때 모듈화하여 사용한다
서로 연관 있는 속성값끼리 병합하여 사용
폴더구조

index.ts
import { createStore } from 'vuex';
import { loginInfo, LoginState } from '@/store/modules/loginInfoModule';
import { settingInfo, SettingState } from '@/store/modules/settingModule';
export interface RootState {
loginInfo: LoginState;
settingInfo: SettingState;
}
export default createStore({
modules: {
loginInfo,
settingInfo,
},
});
loginInfoModule.ts
import { Module } from 'vuex';
import { RootState } from '@/store/index';
export interface LoginState {
userName: string;
email: string;
id: number;
}
export const loginInfo: Module<LoginState, RootState> = {
namespaced: true,
state: {
userName: '',
email: '',
id: 0,
},
getters: {
getLoginInfo(state) {
return state.userName + '(' + state.email + ')';
},
getAllInfo(state, getters, rootState, rootGetters) {
return (
state.userName +
'|' +
getters.getLoginInfo +
'|' +
rootState.loginInfo.userName +
'|' +
rootState.settingInfo.tag +
'|' +
rootGetters['loginInfo/getLoginInfo'] +
'|' +
rootGetters['settingInfo/getInfo']
);
},
},
mutations: {
setLoginInfo(state, info) {
state.userName = info.userName;
state.email = info.email;
state.id = info.id;
},
},
};
settingModule.ts
import { Module } from 'vuex';
import { RootState } from '@/store/index';
export interface SettingState {
tag: string;
}
export const settingInfo: Module<SettingState, RootState> = {
namespaced: true,
state: {
tag: 'setting',
},
getters: {
getInfo(state) {
return '현재 셋팅 정보는 ' + state.tag + '입니다.';
},
},
};
index.ts에는 분리된 모듈만 선언한다.
각 상태값 호출 방식이 변경된다
VuexView.vue
<template>
<div>UserName:{{ store.state.loginInfo.userName }}</div>
<div>string UserName:{{ store.getters['loginInfo/getLoginInfo'] }}</div>
<div>string All:{{ store.getters['loginInfo/getAllInfo'] }}</div>
<input type="button" value="Add" @click="TestMutations" />
</template>
<script lang="ts" setup>
import { useStore } from 'vuex';
import { LoginState } from '@/store/modules/loginInfoModule';
const store = useStore();
const TestMutations = () => {
var l: LoginState = { userName: '테스트', email: 'test@test.com', id: 1 };
store.commit('loginInfo/setLoginInfo', l);
};
</script>
반응형