이번 포스팅에서는 Vuex를 좀 더 고급지게 사용하는 방법을 알아보자.
Modules
모듈이란 애플리케이션을 구성하는 개별적 요소로서 재사용 가능한 코드 조각을 말한다.
예를 들어보자.
// hello.js
export default function hello() {
console.log("hello, everyone!");
}
// index.js
import hello from './hello';
위의 경우와 같이 default를 사용하여 export 하는 경우, import하는 파일에서 기본적으로 가져올 변수나 함수를 지정할 때 사용한다.
즉, import를 하며 기본 값을 받아오는 것이기 때문에 하나의 파일에는 하나의 default 값만이 존재 해야한다.
import로 받아온 명칭은 사용자 정의로 가능하다.
import myHello from './hello';
그럼 default를 사용하지 않은 export한 함수나 변수는 어떻게 import할까?
// hello.js
export default function hello() {
console.log("hello, everyone!");
};
export let variable = "variable plus!";
// index.js
import myCustomHello, { variable } from './hello';
{} 이용하여 변수명 또는 함수명 그대로 import 해오면 된다.
* import 해온 변수나 함수는 기본적으로 raed-only 속성이 적용되어 있어 재정의(override)가 불가하다.
여러 변수나 함수를 한번에 가져오는 방법을 알아보자.
아래 코드를 보자
//hello.js
export function hello() {
console.log("hello, everyone!");
}
export const variable = "variable plus!";
hello()와 variable 두개를 가져오려 한다면 위 방법대로
import { hello, variable } from './hello';
를 이용하여 가져와야 한다.
그럼 변수 + 함수 개수가 100개가 넘는다면..? 이름을 모두 적으면서 import해야할까?
너무 비효율적이다. 한번에 가져오는 방법은
import * as myHello from './hello';
바로 * 키워드를 사용하는 것이다.
이 * 키워드는 흔히 Wild card 라고 하는데, 원래 정규 표현식에서 모든 값을 가지고 오는데 사용하는 키워드로
이 개념이 확장되어서 이곳저곳에서 사용되기 때문에, 보통은 해당 대상의 모든 값을 가지고 온다고 알고있으면 좋다.
이렇게 modules의 특성과 사용방법에 대해 알아보았는데 이 개념을 vuex에도 도입할 수 있다.
todoApp.js
const storage = {
fetch() {
const arr = [];
if (localStorage.length > 0) {
for (let i = 0; i < localStorage.length; i++) {
if (localStorage.key(i) !== "loglevel:webpack-dev-server") {
arr.push(JSON.parse(localStorage.getItem(localStorage.key(i))));
}
}
return arr.sort((a, b) => a.id - b.id);
}
return arr;
}
}
const state = {
todoItems: storage.fetch()
};
const getters = {
storedTodoItems: state => state.todoItems,
completedTodoItems: state => state.todoItems.filter(todoItem => todoItem.completed),
unCompletedTodoItems: state => state.todoItems.filter(todoItem => !todoItem.completed)
};
const mutations = {
addOneItem: (state, todoItem) => {
let id = 1;
if (state.todoItems.length > 0) {
id = state.todoItems[state.todoItems.length - 1].id + 1;
}
const obj = {id: id, completed: false, item: todoItem};
localStorage.setItem(todoItem, JSON.stringify(obj));
state.todoItems.push(obj);
},
removeOneItem: (state, paramItem) => {
localStorage.removeItem(paramItem.item);
let findIdx = state.todoItems.findIndex(todoItem => todoItem.id === paramItem.id );
state.todoItems.splice(findIdx, 1);
},
toggleOneItem: (state, paramItem) => {
let findIdx = state.todoItems.findIndex(todoItem => todoItem.id === paramItem.id );
state.todoItems[findIdx].completed = !state.todoItems[findIdx].completed;
localStorage.removeItem(paramItem.item);
localStorage.setItem(paramItem.item, JSON.stringify(paramItem));
},
sortAllItems: state => {
state.todoItems.sort((a, b) => a.item - b.item);
},
clearAllItems: state => {
state.todoItems = [];
localStorage.clear();
}
}
export default {
state,
getters,
mutations
};
기존에 있던 state, getters, mutations, actions를 todoApp.js 파일에 생성한 다음
modules 속성에 todoApp을 정의한다.
store.js
import Vue from 'vue';
import Vuex from 'vuex';
import todoApp from './modules/todoApp';
Vue.use(Vuex);
const store = new Vuex.Store({
modules: {
todoApp
}
});
export default store;
todoApp.js 를 import 받아온 뒤 modules 속성에 등록한다.
코드가 굉장히 깔끔해지고 기능별로 나뉘어 유지보수에도 굉장히 용이할 것으로 보인다.
이렇게 Vuex의 modules 기능까지 알아보았다.
이것으로 2차 강의가 마무리 되었다.
이번 강의로 사내 프로젝트의 코드를 깔끔하게 정리할 수 있을 것 같다는 생각이 든다.
아직 리팩토링을 진행하고 있진 않지만 추후 리팩토링에 위 개념을 도입하여 정리할 생각이다.
다음은 3차 강의로 돌아오겠다.