[todo] 2. 할일 목록 표시 & 삭제 & 완료 기능 구현

김희주·2023년 1월 14일
0

vue.js

목록 보기
5/13
post-thumbnail

1. 목록 표시 구현

  • todoList
<template>
  <div>
    <ul>
      <li v-for="todoItem in  todoItems" v-bind:key="todoItem">
      {{ todoItem }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data: function() {
    return {
      todoItems : []
    }
  },
  created: function() {             //뷰의 라이프 사이클과 관련된 속성. 인스턴스가 생성되자마자 호출되는 라이프사이클 훅.
      if(localStorage.length > 0) {
        for(var i= 0; i<localStorage.length; i++) {
          if(localStorage.key(i) !== 'loglevel:webpack-dev-server') {
               this.todoItems.push(localStorage.key(i));
          }
        }
      }
  }
}
</script>

2. 삭제 기능 구현

    <ul>
      <li v-for="todoItem in  todoItems" v-bind:key="todoItem">
      {{ todoItem }}</li>
    </ul>

👇

    <ul>
      <li v-for="(todoItem, index) in  todoItems" v-bind:key="todoItem" class="shadow">
      {{ todoItem }} 
      <span class="removeBtn" v-on:click="removeTodo(todoItem, index)">
        <i class="fas fa-solid fa-trash"></i>
      </span>
      </li>
    </ul>
  • splice : 지우고 새로운 배열을 반환
  • slice : 지우고 변경하지 않고 기존 배열을 반환
<template>
  <div>
    <ul>
      <li v-for="(todoItem, index) in  todoItems" v-bind:key="todoItem" class="shadow">
      {{ todoItem }} 
      <span class="removeBtn" v-on:click="removeTodo(todoItem, index)">
        <i class="fas fa-solid fa-trash"></i>
      </span>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data: function() {
    return {
      todoItems : []
    }
  },
  created: function() {             //뷰의 라이프 사이클과 관련된 속성. 인스턴스가 생성되자마자 호출되는 라이프사이클 훅.
      if(localStorage.length > 0) {
        for(var i= 0; i<localStorage.length; i++) {
          if(localStorage.key(i) !== 'loglevel:webpack-dev-server') {
               this.todoItems.push(localStorage.key(i));
          }
        }
      }
  },
  methods : {
    removeTodo : function(todoItem, index) {
      console.log(todoItem, index);
      localStorage.removeItem(todoItem);
      this.todoItems.splice(index,1);
    }
  }
}
</script>

❓ 좀 이해가 안간다...todoItems[]에서 지우면 새로고침 없이 바로 화면에 자동연동된다니...서버랑 통신도 안했는데? 그게 vue의 reactivity 성질인가......!!!!

3. 완료 기능 구현

  • todoInput.vue 수정

    자바스크립트 Object로 들어가기 때문에 로컬스토리지에서 확인이 안됨
    이렇게 되지 않도록
        addTodo : function() {
            if(this.newTodoItem !== '') {
                var obj = {completed : false, item : this.newTodoItem };          //이 아이템이 check됐는지아닌지.
                localStorage.setItem(this.newTodoItem, JSON.stringify(obj));      //객체를 String으로 변환하는 API
                //localStorage.setItem(this.newTodoItem, obj);                      
                this.clearInput();
            } 
        }

  • TodoHeader.vue
<template>
  <header>
    <h1>TODO it!</h1>
  </header>
</template>


<script>
export default {

}
</script>


<style scoped>     /*이 곳에서만 적용되는 style : scoped*/
h1 {
  color: #2F3B52;
  font-weight:900;
  margin: 2.5rem 0 1.5rem;
}
</style>
  • TodoList.vue
<template>
  <div>
    <ul>
      <li v-for="(todoItem, index) in  todoItems" v-bind:key="todoItem.item" class="shadow">
        <i class="checkBtn fas fa-solid fa-check" 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-solid fa-trash"></i>
      </span>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data: function() {
    return {
      todoItems : []
    }
  },
  created: function() {             //뷰의 라이프 사이클과 관련된 속성. 인스턴스가 생성되자마자 호출되는 라이프사이클 훅.
      if(localStorage.length > 0) {
        for(var i= 0; i<localStorage.length; i++) {
          if(localStorage.key(i) !== 'loglevel:webpack-dev-server') {
            this.todoItems.push(JSON.parse(localStorage.getItem(localStorage.key(i))));
          }
        }
      }
  },
  methods : {
    removeTodo : function(todoItem, index) {
      console.log(todoItem, index);
      localStorage.removeItem(todoItem);
      this.todoItems.splice(index,1);
    },
    toggleComplete : function(todoItem, index) {
      todoItem.completed = !todoItem.completed;
      localStorage.removeItem(todoItem.item);
      localStorage.setItem(todoItem.item, JSON.stringify(todoItem));
    }
  }
}
</script>

<style scoped>
ul {
	list-style-type: none;
	padding-left:0px;
	margin-top: 0;
	text-align: left;
}

li {
	display: flex;
	min-height: 50px;
	height:50px;
	line-height: 50px;
	margin: 0.5rem 0;
	padding: 0 0.0rem;
	background: white;
	border-radius: 5px;
}
.checkBtn {
	line-height: 45px;
	color:#62acde;
	margin-right: 5px;
}
.checkBtnCompleted{
	color: #b3adad;
}
.textCompleted{
	text-decoration: line-through;
	color: #b3adad;
}
.removeBtn{
	margin-left: auto;
	color: #de4343;
}
</style>
  • TodoInput.vue
<template>
    <div class="inputBox shadow">
    <input type="text" v-model="newTodoItem" v-on:keyup.enter="addTodo">
    <!-- <button v-on:click="addTodo">등록</button> -->
    <span class="addContainer" v-on:click="addTodo">
        <i class="fas fa-solid fa-plus addBtn"></i>
    </span>
    </div>
</template>

<script>
export default {

    data : function() {
        return {
            newTodoItem : ""
        }
    },
    methods: {
        addTodo : function() {
            if(this.newTodoItem !== '') {
                var obj = {completed : false, item : this.newTodoItem };          //이 아이템이 check됐는지아닌지.
                //객체를 String으로 변환하는 API
                localStorage.setItem(this.newTodoItem, JSON.stringify(obj));      
                //localStorage.setItem(this.newTodoItem, obj);                      
                this.clearInput();
            } 
        },
        clearInput : function() {
            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 {
	color: white;
	vertical-align: middle;
}
</style>
  • TodoFooter.vue
<template>
  <div class="clearAllContainer">
    <span class="clearAllBtn" v-on:click="clearTodo">Clear All</span>
  </div>
</template>

<script>
export default {
    methods : {
      clearTodo : function() {
          localStorage.clear();
      }
    }

}
</script>

<style scoped>
.clearAllContainer {
	width: 8.5rem;
	height: 50px;
	line-height: 50px;
	background-color:white;
	border-radius: 5px;
	margin: 0 auto;
}
.clearAllBtn {
	color: #e20303;
	display: block;
}
</style>
  • 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': TodoHeader,
    'TodoInput': TodoInput,
    'TodoList': TodoList,
    'TodoFooter': 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>
  • main.js
import Vue from 'vue'
import App from './App.vue'

new Vue({
  el: '#app',
  render: h => h(App)
})
profile
백엔드 개발자입니다 ☘

0개의 댓글

관련 채용 정보