본 포스팅은 인프런의 캡틴판교님의 Vue.js 중급 강의를 기반으로 만들어졌습니다.
개요
이전에 todo-list 작성했던 부분은 $emit과 props를 이용해서 만들었었다.
이번에는 이전에 만들었던 todo-list를 vuex를 통해 리펙토링을 진행하였다.
2021.11.11 - [Vue] - [vue] todo-list 생성
[vue] todo-list 생성
본 포스팅은 인프런의 캡틴판교님의 Vue.js 중급 강의를 기반으로 만들어졌습니다. 개요 회사에서 뷰를 사용하기 시작하여 뷰 강의를 듣기 시작하였고 인프런 캡틴판교님의 강의가 유명하다고
nozee.tistory.com
Vuex 설치
- vuex 설치
npm install vuex
vuex 라이브러리가 추가된 것을 확인할 수 있다.
개발 소스
- 파일 구성
기존 소스와 비교하면 vuex 소스를 담는 store 부분을 추가하였다.
- store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const storage = {
initTodo() {
const arr = []
for(var 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
}
}
export const store = new Vuex.Store({
state: {
todos: storage.initTodo()
},
getters : {
storedTodoItems(state){
return state.todos;
}
},
mutations: {
addTodoItem(state,newTodoItem){
let item = {
str : newTodoItem,
done : false
}
localStorage.setItem(newTodoItem, JSON.stringify(item))
state.todos.push(item)
},
clearAllItems(state){
localStorage.clear()
state.todos = []
},
removeTodo(state, str, index){
state.todos.splice(index, 1)
localStorage.removeItem(str)
},
completeTodo(state, modifyTodo, index){
state.todos[index].done = !this.todos[index].done
localStorage.removeItem(modifyTodo.str)
localStorage.setItem(modifyTodo.str, JSON.stringify(this.todos[index]))
}
},
actions: {
}
})
store.js에서는 기존에 App.vue에서 사용했던 data를 state로 가져오고 methods를 mutations으로 가져와 선언을 해주었다.
- main.js
import Vue from 'vue'
import App from './App.vue'
import { store } from './store/stores'
Vue.config.productionTip = false
new Vue({
store,
render: h => h(App),
}).$mount('#app')
main.js 에 새로 생성된 store를 선언해 주어 소스 전체에서 vuex에 접근할 수 있도록 해준다.
- 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>
body {
text-align: center;
background-color : #f6f6f6;
}
input {
border-style : groove;
width: 200px;
}
button {
border-style : groove;
}
.shadow {
box-shadow: 5px 10px 10px rgba(0,0,0,0.03);
}
</style>
App.vue에서 data, methods부분은 store 부분에 선언을 해주었기 때문에 제거하여 준다.
또한 component들에 기존 props와 $emit으로 연결되어 있던 부분들도 제거하여 준다.
- TodoInput.vue
<template>
<div class="inputBox shadow">
<input type="text" v-model="newTodoItem" @keypress.enter="addTodo">
<span class="addContainer" @click="addTodo">
<i class="fas fa-plus addBtn"></i>
</span>
</div>
</template>
<script>
export default {
data() {
return {
newTodoItem : ""
}
},
methods: {
addTodo(){
if(this.newTodoItem == ""){
alert('입력된 값이 없습니다.')
}else{
this.$store.commit('addTodoItem', this.newTodoItem)
this.newTodoItem = ""
}
}
}
}
</script>
<style scoped>
input:focus {
outline: none;
}
.inputBox {
background: white;
height: 50px;
line-height: 50px;
border-radius: 5px;
}
.inputBox input {
border-style: none;
font-size: 0.9rem;
}
.addContainer {
float: right;
background: linear-gradient(to right, #6478FB, #8763FB);
display: block;
width: 3rem;
border-radius: 0 5px 5px 0;
}
.addBtn {
cursor: pointer;
color: white;
vertical-align: middle;
}
.closeModalBtn {
color: #42b983;
}
</style>
TodoInput.vue에서는 기존 addTodo 했던 부분이 $emit으로 App.vue에 있는 addTodoItem을 호출하도록 되어 있었다.
addTodoItem이 store.js로 갔기 때문에 mutations에 선언된 addTodoItem이 호출되도록 변경하였다.
vuex에서 mutations에 선언된 메서드를 호출하기 위해서는 commit 명령어를 사용해서 호출을 한다.
- TodoList.vue
<template>
<ul>
<li v-for="(todo, index) in this.storedTodoItems" :key=todo.str>
<i class="checkBtn fas fa-check" :class="{checkBtnCompleted: todo.done}"
@click="toggleComplete({todo, index})"></i>
<span :class="{textCompleted: todo.done}">{{todo.str}} </span>
<span class="removeBtn" v-on:click="removeTodo({todo, index})">
<i class="fas fa-trash-alt"></i>
</span>
</li>
</ul>
</template>
<script>
import { mapGetters, mapMutations } from 'vuex'
export default {
methods: {
...mapMutations(['removeTodo','toggleComplete'] )
},
computed : {
...mapGetters(['storedTodoItems'])
}
}
</script>
<style scoped>
ul {
list-style-type: none;
padding-left: 0px;
margin-top: 0;
text-align: left;
}
li {
display: flex;
min-height: 50;
height: 50px;
line-height : 50px;
margin: 0.5rem 0;
padding: 0 0.9rem;
background: white;
border-radius: 5px;
}
.checkBtn {
line-height: 45px;
color: #62acde;
margin-right: 5px;
}
.removeBtn {
margin-left: auto;
color : #de4343;
}
.checkBtnCompleted {
color : #b3adad;
}
.textCompleted {
text-decoration: line-through;
color: #b3adad;
}
/* 리스트 아이템 트랜지션 효과 */
.list-enter-active, .list-leave-active {
transition: all 1s;
}
.list-enter, list-leave-to {
opacity: 0;
transform: translateY(30px);
}
</style>
TodoList에서는 기존에 props로 받았던 todo를 store.js에 있는 getters 통해 storedTodoItems로 받도록 변경하였다.
removeTodo, toggleComplete도 마찬가지로 mutations에 있는 메서드가 호출되도록 변경하였다.
vuex를 import 해주게 되면 mapState, mapGetters, mapMutations, mapActions를 접근할 수 있게 된다.
es6에서 제공하는 전개 연산자와 같이 사용하면 위에 소스와 같은 형태로 vuex에 접근할 수 있게 된다.
- TodoFooter.vue
<template>
<div class="clearAllContainer">
<span class="clearAllBtn" @click="clearAllItems">Clear All</span>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
methods: {
...mapMutations(['clearAllItems'])
},
}
</script>
<style>
.clearAllContainer {
width: 8.5rem;
height: 50px;
line-height: 50px;
background-color: white;
border-radius: 5px;
margin: 0 auto;
}
.clearAllBtn {
cursor: pointer;
color: #e20303;
display: block;
}
</style>
TodoFooter.vue도 TodoList.vue와 마찬가지로 vuex를 import 하여 mapMutations를 가져왔고 mapMutations에 clearAllItems를 가져오도록 하였다.
개발 화면
본 포스팅은 여기까지 입니다.
읽어주셔서 감사합니다.
'Vue' 카테고리의 다른 글
[vue] todo-list 생성 (0) | 2021.11.11 |
---|