728x90
반응형
Todo App
간단한 일정관리 App으로 기본 CRUD를 구현하기 적합하다.
구조
<Root>
<App>
<TodoHeader>
<TodoInput>
<TodoList>
<TodoFooter>
컴포넌트 생성 및 등록하기
1. src/components
에 필요한 컴포넌트용 vue파일
생성
2. App.vue에 컴포넌트용 vue파일
import
// 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>
파비콘, 반응형 웹, 폰트, 아이콘 태그 설정하기
// index.html
...
<head>
<!-- 반응형 태그 -->
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<!-- favicon 설정 -->
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<!-- fontawesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css"/>
<!-- google font -->
<link href="https://fonts.googleapis.com/css2?family=Ubuntu&display=swap" rel="stylesheet">
</head>
...
TodoHeader 구현
기능
- App 제목
// TodoHeader.vue
<template>
<div>
<h1>TODO it!</h1>
</div>
</template>
<style scoped>
/* scoped 선언 시 해당 컴포넌트에서만 유효하다는 선언 */
h1 {
color: #2F3B52;
font-weight: 900;
margin: 2.5rem 0 1.5rem;
}
</style>
TodoInput 구현
기능
- 할 일 추가 (버튼 클릭, 엔터키 이벤트)
localStorage
에 객체로 할 일, 완료여부 저장- 저장 후 입력란 비우기
// TodoInput.vue
<template>
<div class="inputBox shadow">
<!-- enter 입력 시 addTodo 함수 실행 -->
<input type="text" v-model="newTodoItem" v-on:keyup.enter="addTodo">
<!-- 클릭 시 addTodo 함수 실행 -->
<span class="addContainer" v-on:click="addTodo">
<i class="fas 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};
// 저장하는 로직 수행
// logcalStorage.setItem(key, value);
// JSON.stringify() 객체를 String으로 변환
localStorage.setItem(this.newTodoItem, JSON.stringify(obj));
this.clearInput();
}
},
clearInput: function() {
// input 값 비우기
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>
LocalStorage 확인
TodoList 구현
기능
localStorage
에 저장된 할 일 목록 표시- 체크 클릭 시 완료여부 변경
- 휴지통 클릭 시 할 일 삭제 (
localStorage
와 화면 스크립트 둘 다)
// TodoList.vue
<template>
<div>
<ul>
<!-- v-for 사용 시 v-bind:key 사용하지 않아도 무방(VSCode에서는 에러문구 출력) -->
<li v-for="(todoItem, index) in todoItems" v-bind:key="todoItem.item" class="shadow">
<!-- v-bind:class="{checkBtnCompleted: todoItem.completed}"는 todoItem.completed의 true/false에 따라 동적으로 class 추가/삭제 기능 -->
<i class="checkBtn fas fa-check" v-bind:class="{checkBtnCompleted: todoItem.completed}" v-on:click="toggleComplete(todoItem)"></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>
</ul>
</div>
</template>
<script>
export default {
data: function() {
return {
todoItems: []
}
},
methods: {
removeTodo: function(todoItem, index) {
// localStorage에 저장된 값 지우기
// localStorage.removeItem(key);
localStorage.removeItem(todoItem);
// localStroage영역만 지우는게 아니라 화면 스크립트 영역도 지워야 한다
// splice(배열의 변경을 시작할 인덱스, 배열에서 제거할 요소의 수, [배열에 추가할 요소])
this.todoItems.splice(index, 1);
},
toggleComplete: function(todoItem) {
// completed 변경
todoItem.completed = !todoItem.completed;
// localStorage에 update가 없기 때문에
// 기존걸 지우고
localStorage.removeItem(todoItem.item);
// 변경된 정보로 다시 저장
localStorage.setItem(todoItem.item, JSON.stringify(todoItem));
}
},
// 뷰 라이프사이클 설정
created: function() {
// localStorage에 저장된 값 꺼내 todoItems에 넣기
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))));
}
}
}
}
}
</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.9rem;
background: white;
border-radius: 5px;
}
.removeBtn {
margin-left: auto;
color: #de4343;
}
.checkBtn {
line-height: 45px;
color: #62acde;
margin-right: 5px;
}
.checkBtnCompleted {
color: #b3adad;
}
.textCompleted {
text-decoration: line-through;
color: #b3adad;
}
</style>
TodoFooter 구현
기능
localStorage
에 저장된 할 일 전체 제거
// 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 비우기
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>
완료 화면
728x90
반응형
'Dev > Vue.js' 카테고리의 다른 글
[Vue.js] Todo App 사용자 경험 개선하기 (0) | 2020.09.10 |
---|---|
[Vue.js] Todo App 개선하기 (0) | 2020.09.10 |
[Vue.js] 싱글 파일 컴포넌트 (0) | 2020.09.09 |
[Vue.js] Vue CLI (0) | 2020.09.09 |
[Vue.js] 템플릿 문법 - 실전 (0) | 2020.09.08 |
댓글