todo 앱
💻todo1 프로젝트
MyTodo.vue 생성
<template>
<div>
<h1>할 일</h1>
<table>
<tr><td>ID</td><td>할일</td></tr>
<tr v-for="todo in todos" v-bind:key="todo.id"> //index로 구현하면 안됨
<td>{{ todo.id }}</td>
<td>{{ todo.title }}</td>
</tr>
</table>
</div>
</template>
<script>
export default {
name: "MyTodo",
data() {
return {
todos: [
{ id: 1, title: "과제" },
{ id: 2, title: "시험공부" },
{ id: 3, title:"코딩훈련" }
]
}
}
}
</script>
<style scoped>
h1 { border-bottom: 1px solid gray; }
div { padding: 30px; margin: 30px auto; width: 400px;
border: 1px solid #ccc; box-shadow: 3px 3px 3px #aaa; }
table { border-collapse: collapse; margin: 20px 0; width: 100%; }
tr:nth-child(1) { background-color: #eee; text-align: center; }
td { border: 1px solid gray; padding: 6px; }
td:nth-child(1) { text-align: center; width: 30px; }
</style>
App.vue
<template>
<div id="app">
<MyTodo />
</div>
</template>
<script>
import MyTodo from './MyTodo.vue'
export default {
name: "App",
components: { MyTodo }
}
</script>
<style scoped>
</style>
➕MyTodo.vue 추가 기능
<template>
<div>
<h1>할 일</h1>
<table>
<tr><td>ID</td><td>할일</td></tr>
<tr v-for="todo in todos" v-bind:key="todo.id">
<td>{{ todo.id }}</td>
<td>{{ todo.title }}</td>
</tr>
</table>
<input type="text" v-model="title" />//할 일 입력 칸
<button type="button" v-on:click="addTodo">추가</button> //할 일 추가 버튼
</div>
</template>
<script>
export default {
name: "MyTodo",
data() {
return {
todos: [
{ id: 1, title: "과제" },
{ id: 2, title: "시험공부" },
{ id: 3, title:"코딩훈련" }
],
title: "",
lastId: 3
}
},
methods: {
addTodo: function() {
this.todos.push({id: ++this.lastId, title: this.title});
this.title = "";
}
}
}
</script>
<style scoped>
h1 { border-bottom: 1px solid gray; }
div { padding: 30px; margin: 30px auto; width: 400px;
border: 1px solid #ccc; box-shadow: 3px 3px 3px #aaa; }
table { border-collapse: collapse; margin: 20px 0; width: 100%; }
tr:nth-child(1) { background-color: #eee; text-align: center; }
td { border: 1px solid gray; padding: 6px; }
td:nth-child(1) { text-align: center; width: 30px; }
input[type=text] { padding: 5px; margin-right: 5px; width: 300px; }
button { padding: 0.3em 1.5em; }
</style>
🚮MyTodo.vue - 삭제 기능
<template>
<div>
<h1>할 일</h1>
<table>
<tr><td>ID</td><td>할일</td></tr>
<tr v-for="(todo, index) in todos" v-bind:key="todo.id">
<td>{{ todo.id }}</td>
<td>
{{ todo.title }}
<span v-on:click="deleteTodo(index)">x</span> //누르면 삭제
</td>
</tr>
</table>
<input type="text" v-model="title" />
<button type="button" v-on:click="addTodo">추가</button>
</div>
</template>
<script>
export default {
name: "MyTodo",
data() {
return {
todos: [
{ id: 1, title: "과제" },
{ id: 2, title: "시험공부" },
{ id: 3, title:"코딩훈련" }
],
title: "",
lastId: 3
}
},
methods: {
addTodo: function() {
this.todos.push({id: ++this.lastId, title: this.title});
this.title = "";
},
deleteTodo(index) {
if (confirm("삭제하시겠습니까?"))
this.todos.splice(index, 1);
}
}
}
</script>
<style scoped>
h1 { border-bottom: 1px solid gray; }
div { padding: 30px; margin: 30px auto; width: 400px;
border: 1px solid #ccc; box-shadow: 3px 3px 3px #aaa; }
table { border-collapse: collapse; margin: 20px 0; width: 100%; }
tr:nth-child(1) { background-color: #eee; text-align: center; }
td { border: 1px solid gray; padding: 6px; }
td:nth-child(1) { text-align: center; width: 30px; }
input[type=text] { padding: 5px; margin-right: 5px; width: 300px; }
button { padding: 0.3em 1.5em; }
span { font-weight: bold; margin-left: 10px; cursor: pointer; float: right;}
</style>
✅MyTodo.vue - 할 일 완료 표시
<template>
<div>
<h1>할 일</h1>
<table>
<tr><td>ID</td><td>할일</td></tr>
<tr v-for="(todo, index) in todos" v-bind:key="todo.id" v-bind:class="{done: todo.done}"> //done이 true가 되면 해당 클래스 style 속성이 적용
<td>{{ todo.id }}</td>
<td>
<input type="checkbox" v-model="todo.done" /> //할 일 완료 체크박스
{{ todo.title }}
<span v-on:click="deleteTodo(index)">x</span>
</td>
</tr>
</table>
<input type="text" v-model="title" />
<button type="button" v-on:click="addTodo">추가</button>
</div>
</template>
<script>
export default {
name: "MyTodo",
data() {
return {
todos: [
{ id: 1, title: "과제", done: false },
{ id: 2, title: "시험공부", done: false },
{ id: 3, title:"코딩훈련", done: false }
],
title: "",
lastId: 3
}
},
methods: {
addTodo: function() {
this.todos.push({id: ++this.lastId, title: this.title});
this.title = "";
},
deleteTodo(index) {
if (confirm("삭제하시겠습니까?"))
this.todos.splice(index, 1);
}
}
}
</script>
<style scoped>
h1 { border-bottom: 1px solid gray; }
div { padding: 30px; margin: 30px auto; width: 400px;
border: 1px solid #ccc; box-shadow: 3px 3px 3px #aaa; }
table { border-collapse: collapse; margin: 20px 0; width: 100%; }
tr:nth-child(1) { background-color: #ddd; text-align: center; }
td { border: 1px solid gray; padding: 6px; }
td:nth-child(1) { text-align: center; width: 30px; }
input[type=text] { padding: 5px; margin-right: 5px; width: 300px; }
button { padding: 0.3em 1.5em; }
span { font-weight: bold; margin-left: 10px; cursor: pointer; float: right;}
tr.done { background-color: #f8f8f8; color: #bbb; text-decoration: line-through; }
input[type=checkbox] { accent-color: #bbb; }
</style>
📚연습문제
![](https://velog.velcdn.com/images/qorgus31/post/069e351e-a60b-40e1-8630-87ebc9478b8d/image.png)
MyTodo.vue
<template>
<div>
<h1>할 일</h1>
<table>
<tr><td>ID</td><td>기한</td><td>할일</td></tr>
<tr v-for="(todo, index) in todos" v-bind:key="todo.id" v-bind:class="{done: todo.done}">
<td>{{ todo.id }}</td>
<td>{{ todo.date }}</td> //날짜 출력
<td>
<input type="checkbox" v-model="todo.done" />
{{ todo.title }}
<span v-on:click="deleteTodo(index)">x</span>
</td>
</tr>
</table>
<input type="text" v-model="title" placeholder="할일을 입력하세요"/>
<input type="date" v-model="date"> //date 속성 input 태그
<button type="button" v-on:click="addTodo">추가</button>
</div>
</template>
<script>
export default {
name: "MyTodo",
data() {
return {
todos: [
{ id: 1, title: "과제", date: "2023-05-20", done: false },
{ id: 2, title: "시험공부", date: "2023-06-01", done: false },
{ id: 3, title:"코딩훈련",date: "2023-06-01", done: false }
],
title: "",
lastId: 3
}
},
methods: {
addTodo: function() {
this.todos.push({id: ++this.lastId, date: this.date, title: this.title});
this.title = "";
},
deleteTodo(index) {
if (confirm("삭제하시겠습니까?"))
this.todos.splice(index, 1);
}
}
}
</script>
<style scoped>
h1 { border-bottom: 1px solid gray; }
div { padding: 30px; margin: 30px auto; width: 500px;
border: 1px solid #ccc; box-shadow: 3px 3px 3px #aaa; }
table { border-collapse: collapse; margin: 20px 0; width: 100%; }
tr:nth-child(1) { background-color: #ddd; text-align: center; }
td:nth-child(2) { width: 100px; text-align: center; }
td { border: 1px solid gray; padding: 6px; }
td:nth-child(1) { text-align: center; width: 30px; }
input[type=text] { padding: 5px; margin-right: 5px; width: 300px; }
button { padding: 0.3em 1.5em; margin-left : 5px; width: 60px;}
span { font-weight: bold; margin-left: 10px; cursor: pointer; float: right;}
tr.done { background-color: #f8f8f8; color: #bbb; text-decoration: line-through; }
input[type=checkbox] { accent-color: #bbb; }
</style>