728x90
★ TodoList
- 할일을 적고 해당 사항들을 수행해 나가는 List
- Step1 ~ Step4에 대한 내용을 가지고 해당 기능을 개발
1. 기본 UI 개발
- 큰 틀 잡기
<style>
body { margin : 0; padding : 0; font-family: sans-serif; }
.title { text-align: center; font-weight: bold; font-size: 20pt; }
.todo-done { text-decoration: line-through; }
.container { padding:10px 10px 10px 10px; }
.panel-borderless { border : 0; box-shadow: none; }
.pointer { cursor : pointer; }
</style>
</head>
<body>
<div id="app" class="container">
<div class="card card-body bg-light">
<div class="title">:: Todolist App</div>
</div>
<div class="card card-default card-borderless">
<div class="card-body">
<!-- 본문 내용 삽입 -->
</div>
</div>
</div>
<script type="text/javascript" src="https://unpkg.com/vue"></script>
<script type="text/javascript">
</script>
</body>
- 본문 내용 삽입
<div class="row mb-3">
<div class="col">
<div class="input-group">
<input id="msg" type="text" class="form-control" name="msg" placeholder="할일을 여기에 입력하세요!" />
<span class="btn btn-primary input-group-addon">추가</span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<ul class="list-group">
<li class="list-group-item list-group-item-success">
<span class="todo-done pointer">할일 1 (완료)</span>
<span class="float-end badge bg-secondary pointer">삭제</span>
</li>
<li class="list-group-item">
<span class="pointer">할일2</span>
<span class="float-end badge bg-secondary pointer">삭제</span>
</li>
<li class="list-group-item">
<span class="pointer">할일3</span>
<span class="float-end badge bg-secondary pointer">삭제</span>
</li>
</ul>
</div>
</div>
2. 데이터와 메서드 정의
[ 데이터 ] | |
todo | 텍스트 박스에 사용자가 입력하는 내용을 받아내기 위한 data 입니다. |
todolist | 추가한 todo 들의 목록, todo 한 건은 다음과 같습니다. |
id | todo 한 건의 고유 키, 이 예제에서는 timestamp를 이용합니다. |
todo | todo 내용 |
completed | 완료 여부(true, false) |
[ 메서드 ] | |
addTodo | 텍스트 박스에 사용자가 입력하는 내용을 받아내기 위한 data 입니다. |
deleteTodo | 추가한 todo 들의 목록, todo 한 건은 다음과 같습니다. |
toggleCompleted | todo 한 건의 고유 키, 이 예제에서는 timestamp를 이용합니다. |
- 정의한 데이터와 메서드를 토대로 Vue 인스턴스 코드를 작성하면
var ts = new Data().getTime()
var vm = Vue.createApp({
name : "App",
data() {
return {
todo : "",
todolist : [
{ id : ts, todo:"Vue 공부하기", completed : false},
{ id : ts+1, todo:"Vue 실습하기", completed : true},
{ id : ts+2, todo:"Toy Project", completed : false},
{ id : ts+3, todo:"Spring Boot 공부", completed : false},
]
}
},
methods : {
addTodo() {
if (this.todo.length >= 2) {
this.todolist.push({ id : new Date().getTime(),
todo: this.todo, completed: false });
this.todo = ""
}
},
deleteTodo(id) {
let index = this.todolist.findIndex((item)=> id === item.id);
this.todolist.splice(index, 1);
},
toggleCompleted(id) {
let index = this.todolist.findIndex((item)=> id === item.id);
this.todolist[index].completed = !this.todolist[index].completed;
}
}
}).mount("#app")
3. 템플릿 작성
<div id="app" class="container">
<div class="card card-body bg-light">
<div class="title">:: Todolist App</div>
</div>
<div class="card card-default card-borderless">
<div class="card-body">
<!-- 이곳에 삽입 될 예쩡 -->
<div class="row mb-3">
<div class="col">
<div class="input-group">
<input id="msg" type="text" class="form-control" name="msg" placeholder="할일을 여기에 입력하세요!"
v-model.trim="todo" @keyup.enter="addTodo" />
<span class="btn btn-primary input-group-addon" @click="addTodo">추가</span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<ul class="list-group">
<li v-for="todoitem in todolist" :key="todoitem.id"
class="list-group-item"
:class="{ 'list-group-item-success' : todoitem.completed }"
@click="toggleCompleted(todoitem.id)" >
<span class="pointer" :class="{ 'todo-done' : todoitem.completed }">
{{todoitem.todo}} {{ todoitem.completed ? "(완료)" : ""}}
</span>
<span class="float-end badge bg-secondary pointer"
@click.stop="deleteTodo(todoitem.id)">삭제</span>
</ul>
</div>
</div>
</div>
</div>
</div>
4. 설명
4.1 5행~
- 할일(todo)을 사용자로부터 입력받을 수 있게 v-model 디렉티브를 이용해, 양방향으로 바인딩.
- 앞뒤 공백 문자를 자동으로 제거할 수 있도록 .trim 수식어를 지정.
- 입력 후, enter키를 누르면, addTodo() 메서드를 실행해 한 건의 todo가 추가.
- 동일하게, 추가 버튼을 클릭하여도, addTodo() 메서드를 실행
4.2 15행~
- <li> 요소는 todolist 내부의 아이템 수만큼 반복 렌더링해야 하므로, v-for 디렉티브를 사용.
- :key 특성은 반드시 고유 키를 부여해야 하므로, id 필드를 부여하도록 한다.
- <li> 요소는 완료 여부에 따라 다르게 스타일링 되어야 하므로, 달라질 스타일로 구분하여
- 정적인 스타일 : class="list-group-item", 달라질 스타일 : true,false 값을 가지는 객체이므로 -> :class 로 바인딩
4.3 18행, 23행
- 완료를 토글 처리하는 이벤트와 삭제 처리하는 이벤트를 등록
- 삭제 처리 : 이벤트 .stop 수식어를 등록했음에 유의. 이 수식어를 작성하지 않고 삭제 버튼을 클릭하면 이벤트가 버블링하면서 완료 토글 이벤트까지 실행되면서 오류가 발생한다.
5. 실행 화면
6. 마무리
- 템플릿 코드의 작성보다 화면 시안을 반영해 data와 data의 변경을 일으키는 메서드의 작성을 먼저 진행해야한다.
화면 시안 -> data 정의 -> 메서드 정의 -> 템플릿 작성
728x90
'Vue.js' 카테고리의 다른 글
Vue.js 3.0 STEP 7 - TodoList 리팩토링 (0) | 2024.01.25 |
---|---|
Vue.js 3.0 STEP 6 - 단일 파일 컴포넌트 (2) | 2024.01.25 |
Vue.js 3.0 STEP 4 - 스타일 적용 (0) | 2024.01.25 |
Vue.js 3.0 STEP 3 - 이벤트 처리 (0) | 2024.01.18 |
Vue.js 3.0 STEP 2 - Vue 인스턴스 (0) | 2024.01.18 |