Todo App 리팩토링
사용 기술
ES6
Vuex
Vuex Helper
- Vuex 프로젝트 구조화와 모듈화
store.js
| import Vue from "vue"; |
| import Vuex from "vuex"; |
| |
| |
| import todoApp from './modules/todoApp.js' |
| |
| Vue.use(Vuex); |
| |
| export const store = new Vuex.Store({ |
| modules: { |
| todoApp |
| } |
| }); |
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; |
| }, |
| }; |
| |
| const state = { |
| todoItems: storage.fetch(), |
| }; |
| |
| const getters = { |
| storedTodoItems(state) { |
| return state.todoItems; |
| }, |
| }; |
| |
| const mutations = { |
| addOneItem(state, todoItem) { |
| const obj = { completed: false, item: todoItem }; |
| localStorage.setItem(todoItem, JSON.stringify(obj)); |
| state.todoItems.push(obj); |
| }, |
| removeOneItem(state, payload) { |
| localStorage.removeItem(payload.todoItem.item); |
| state.todoItems.splice(payload.index, 1); |
| }, |
| toggleOneItem(state, payload) { |
| state.todoItems[payload.index].completed = !state.todoItems[payload.index] |
| .completed; |
| localStorage.removeItem(payload.todoItem.item); |
| localStorage.setItem( |
| payload.todoItem.item, |
| JSON.stringify(payload.todoItem) |
| ); |
| }, |
| clearAllItems(state) { |
| localStorage.clear(); |
| state.todoItems = []; |
| }, |
| }; |
| |
| export default { |
| state, |
| getters, |
| mutations |
| } |
App.vue
| <template> |
| <div id="app"> |
| <TodoHeader></TodoHeader> |
| <TodoInput></TodoInput> |
| <TodoList></TodoList> |
| <TodoFooter></TodoFooter> |
| </div> |
| </template> |
| |
| <script> |
| import TodoHeader from "./components/TodoHeader.vue"; |
| import TodoInput from "./components/TodoInput.vue"; |
| import TodoList from "./components/TodoList.vue"; |
| import TodoFooter from "./components/TodoFooter.vue"; |
| |
| export default { |
| components: { |
| TodoHeader, |
| TodoInput, |
| TodoList, |
| TodoFooter, |
| }, |
| }; |
| </script> |
| |
| <style></style> |
TodoInput.vue
| <template> |
| <div class="inputBox shadow"> |
| <input type="text" v-model="newTodoItem" v-on:keyup.enter="addTodo" /> |
| <span class="addContainer" v-on:click="addTodo"> |
| <i class="fas fa-plus addBtn"></i> |
| </span> |
| <Modal v-if="showModal" @close="showModal=false"> |
| <h3 slot="header"> |
| 경고 ! |
| <i class="closeModalBtn fas fa-times" @click="showModal = false"></i> |
| </h3> |
| <div slot="body">값을 입력하세요.</div> |
| </Modal> |
| </div> |
| </template> |
| |
| <script> |
| import Modal from "./common/Modal.vue"; |
| |
| export default { |
| data() { |
| return { |
| newTodoItem: "", |
| showModal: false, |
| }; |
| }, |
| methods: { |
| addTodo() { |
| if (this.newTodoItem !== "") { |
| this.$store.commit("addOneItem", this.newTodoItem); |
| this.clearInput(); |
| } else { |
| this.showModal = !this.showModal; |
| } |
| }, |
| clearInput() { |
| this.newTodoItem = ""; |
| }, |
| }, |
| components: { |
| Modal, |
| }, |
| }; |
| </script> |
| |
| <style scoped></style> |
TodoList.vue
| <template> |
| <div> |
| <transition-group name="list" tag="ul"> |
| <li |
| v-for="(todoItem, index) in this.storedTodoItems" |
| v-bind:key="todoItem.item" |
| class="shadow" |
| > |
| <i |
| class="checkBtn fas fa-check" |
| v-bind:class="{checkBtnCompleted: todoItem.completed}" |
| v-on:click="toggleComplete({todoItem, index})" |
| ></i> |
| <span v-bind:class="{textCompleted: todoItem.completed}">{{ todoItem.item }}</span> |
| <span class="removeBtn" v-on:click="removeTodo({todoItem, index})"> |
| <i class="fas fa-trash"></i> |
| </span> |
| </li> |
| </transition-group> |
| </div> |
| </template> |
| |
| <script> |
| import { mapGetters, mapMutations } from "vuex"; |
| |
| export default { |
| methods: { |
| ...mapMutations({ |
| removeTodo: "removeOneItem", |
| toggleComplete: "toggleOneItem", |
| }), |
| }, |
| computed: { |
| ...mapGetters(["storedTodoItems"]), |
| }, |
| }; |
| </script> |
| |
| <style scoped></style> |
TodoFooter.vue
| <template> |
| <div class="clearAllContainer"> |
| <span class="clearAllBtn" v-on:click="clearTodo">Clear All</span> |
| </div> |
| </template> |
| |
| <script> |
| import { mapMutations } from "vuex"; |
| |
| export default { |
| methods: { |
| ...mapMutations({ |
| clearTodo: "clearAllItems", |
| }), |
| }, |
| }; |
| </script> |
| |
| <style scoped></style> |
댓글