Node.js : 16.13.0
Vue : 3.2.21
Vite : 2.6.13
vuex : 4.0.2
vue-router : 4.0.12
0. 사전 준비
# Node.js
- 자바스크립트 패키지 매니저인 npm을 사용하기 때문에 Node.js를 설치해주자.
https://next.vuex.vuejs.org/installation.html
# Vite
https://vitejs.dev/guide/#scaffolding-your-first-vite-project
npm init vite@latest
cd test
npm install
npm run dev
- test 대신에 입력한 프로젝트 명
- Vue-CLI 대신에 Vite를 활용해서 Vue 개발 준비를 한다.
# Vue3
- 공식문서를 참조.
https://v3.ko.vuejs.org/guide/installation.html
1. 라이브러리 설정
# Vue Router
npm install vue-router@4
- 공식문서를 참조.
https://next.router.vuejs.org/installation.html
// src/router.ts
import { createWebHistory, createRouter } from "vue-router";
const routes = [
{
path: "/",
name: "Home",
component: () => import("./views/Home.vue"),
},
{
path: "/test",
name: "Test",
component: () => import("./views/Test.vue"),
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
- 라우터 설정 파일
// src/main.ts
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router"; // 추가
createApp(App).use(router).mount("#app"); // .use(router) 추가
- router 인스턴스를 사용해줘야한다.
<!-- src/App.vue -->
<template>
<div>
<router-view />
</div>
</template>
- <router-view />에서 경로가 일치하는 컴포넌트를 렌더링한다.
# Vuex
npm install vuex@next --save
- 공식문서를 참조.
https://next.vuex.vuejs.org/installation.html
// src/store/index.ts
import Vuex, { StoreOptions } from "vuex";
import moduleA from "./modules/ModuleA";
import moduleB from "./modules/ModuleB";
export interface RootState {
data: string;
}
const store: StoreOptions<RootState> = {
state: { data: "root" },
modules: { moduleA, moduleB },
mutations: {
setData(state, data: string) {
// -> commit('setData')
state.data = data;
},
},
actions: {
setRootData({ commit }, data: string) {
// -> dispatch('setRootData')
console.log("RootState set Root Data");
commit("setData", data);
},
},
getters: {
data: (state) => state.data, // -> getters['data']
},
};
export default new Vuex.Store(store);
- vuex 저장소 구분을 위해 모듈을 사용
// src/store/modules/ModuleA.ts
import { Module } from "vuex";
import { RootState } from "../index";
import ModuleA from "../../types/ModuleAType";
const module: Module<ModuleA, RootState> = {
namespaced: true, // 추가
state: { data: "ModuleA Data" },
mutations: {
setData(state, data: string) {
// -> commit('moduleA/setData')
state.data = data;
},
},
actions: {
setRootData({ commit }, data: string) {
// -> dispatch('moduleA/setRootData')
console.log("module A set Root Data");
commit("setData", data);
},
},
getters: { data: (state) => state.data }, // -> getters['moduleA/data']
};
export default module;
- namespaced: true rootState와 구분해 주기 위한 옵션
- 밑의 공식 문서에서 확인
https://next.vuex.vuejs.org/guide/modules.html#namespacing
// src/store/modules/ModuleB.ts
import { Module } from "vuex";
import { RootState } from "../index";
import ModuleB from "../../types/ModuleBType";
const module: Module<ModuleB, RootState> = {
namespaced: true,
state: { data: "ModuleB Data" },
mutations: {
setData(state, data: string) {
// -> commit('moduleB/setData')
state.data = data;
},
},
actions: {
setRootData({ commit }, data: string) {
// -> dispatch('moduleB/setRootData')
console.log("module B set Root Data");
commit("setData", data);
},
},
getters: { data: (state) => state.data }, // -> getters['moduleB/data']
};
export default module;
// src/types/ModuleAType.ts
export default interface ModuleA {
data: string;
}
// src/types/ModuleBType.ts
export default interface ModuleB {
data: string;
}
// src/main.ts
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"); // .use(store) 추가
2. 적용 확인
<!-- src/views/Home.vue -->
<template>
<div>
<h1>안뇽 !</h1>
<h2>라우터 테스트</h2>
<router-link :to="routerTest">vuex 테스트하러 가기</router-link>
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "Home",
data() {
return {
routerTest: "/test",
};
},
});
</script>
<style>
</style>
<!-- src/views/Test.vue -->
<template>
<div>
<h2>{{ rootStateData }}</h2>
<button @click="setRoot">Set Root Data</button>
<h2>{{ moduleAData }}</h2>
<button @click="setModuleA">Set ModuleA Data</button>
<h2>{{ moduleBData }}</h2>
<button @click="setModuleB">Set ModuleB Data</button>
</div>
</template>
<script lang="ts">
import { defineComponent, computed } from "vue";
import { useStore } from "vuex";
export default defineComponent({
name: "Test",
setup() {
const { state, dispatch } = useStore();
const rootStateData = computed(() => state.data);
const moduleAData = computed(() => state.moduleA.data);
const moduleBData = computed(() => state.moduleB.data);
const setRoot = () => dispatch("setRootData", "testRoot"); //RootState
const setModuleA = () => dispatch("moduleA/setRootData", "testModuleA"); //ModuleState
const setModuleB = () => dispatch("moduleB/setRootData", "testModuleB"); //ModuleState
return {
rootStateData,
moduleAData,
moduleBData,
setRoot,
setModuleA,
setModuleB,
};
},
});
</script>
<style>
</style>
3. 마치며
- Vue CLI 대신 Vite(빗)을 사용해서 Vue 개발 설정
- Vue 3.x 부터는 typescript로 재작성 되었기에 이참에 typescript를 공부할겸 사용
- 많이 사용하는 vue-router, vuex 라이브러리를 Vue3에 적용
- 다음에는 오랜만에 django로 벡엔드를 구축하여 axios를 활용하여 벡과 통신을 시도해봐야겠다.