[Vue] 6. TODO-APP 만들기
TODO-APP 만들기
11. TODO-APP 프로젝트 생성
다시 vue-cli로 todo-app라는 새로운 프로젝트를 생성해줍니다.
vue init webpack vue-todo-app
cd vue-todo-app
npm run dev
12. TODO-APP 퍼블리셔 작업
간단한 앱이니까 todo-list 부트스트랩 샘플을 찾아서 우선 기본적인 틀과 CSS 작업을 먼저하겠다. todoApp 컴포넌트와 목록을 루핑할 todoList 생성해주고 라우터를 수정한다.
index.html
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no">
<title>todo-app</title>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
components/todoApp.vue
todo App의 메인 컴포넌트이다.
<template>
<div class="todoApp">
<div class="form-group">
<h1><span class="vue">Vue</span> To-Do
<small>List</small>
</h1>
<form role="form">
<input type="text" class="form-control" placeholder="해야 할 일">
</form>
<button type="button" class="btn btn btn-primary">Add</button>
</div>
<div class="todo-list">
<!-- todoList 컴포넌트 -->
<todoList></todoList>
</div>
</div>
</template>
<script>
// todoList 컴포넌트 import
import todoList from '@/components/todoList'
export default {
name: 'todoApp',
components: {
'todoList': todoList
}
}
</script>
<style scoped>
.todoApp {
margin: auto;
width: 500px;
}
form {
display: inline-block;
}
.form-group {
text-align: center;
margin-top: 10em;
padding-bottom: 25px;
}
.todo-list {
width: 250px;
text-align: left;
margin-left: 130px;
}
a.close {
float: right;
}
.vue {
color: #009900;
}
</style>
components/todoList.vue
todo-list 컴포넌트이다.
<template>
<div>
<ul class="list-unstyled">
<li>1. 운동하기</li>
<li>2. JAVA</li>
<li>3. javascript</li>
</ul>
</div>
</template>
<script>
export default {
name: 'todoList'
};
</script>
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import todoApp from '@/components/todoApp'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'todoApp',
component: todoApp
}
]
})
다시 화면을 띄우면 아래와 같이 뜨면 정상이다.
13. TODO-APP 목록 데이터 렌더링
todoApp에서 Props로 데이터를 todoList 자식 컴포넌트로 전달해서 목록을 렌더링하겠습니다.
components/todoApp.vue 부분
동적으로 속성에 데이터 바인딩을 하기 위해서 v-bind 디렉티브를 추가합니다. <todoList v-bind:todos="todos"
></todoList>
<template>
<div class="todoApp">
<div class="form-group">
<h1><span class="vue">Vue</span> To-Do
<small>List</small>
</h1>
<form role="form">
<input type="text" class="form-control" placeholder="해야 할 일">
</form>
<button type="button" class="btn btn btn-primary">Add</button>
</div>
<div class="todo-list">
<!-- todoList 컴포넌트: v-bind(디렉티브) Element 객체의 속성 동적 데이터 바인딩 -->
<todoList v-bind:todos="todos"></todoList>
</div>
</div>
</template>
<script>
// todoList 컴포넌트 import
import todoList from '@/components/todoList'
export default {
name: 'todoApp',
// data
data(){
return {
title:'',
todos:[
{
title: '운동하기'
},
{
title: 'JAVA'
},
{
title: 'javascript'
},
{
title: '영어'
}
]
}
},
components: {
'todoList': todoList
}
}
</script>
components/todoList.vue
<template>
<div>
<ul v-for="(todo, i) in todos" :key="todos.id" class="list-unstyled">
`{`{i+1`}`}. `{`{todo.title`}`} <span class="close" aria-hidden="true">×</span>
</ul>
</div>
</template>
<script>
export default {
name: 'todoList',
props: ['todos']
};
</script>
우선 List 작업은 끝났다. 다시 보면 데이터가 렌더링된 화면을 볼 수 있다.
14. TODO-APP 등록 데이터 렌더링
이제 [add] 버튼을 클릭 시 등록되는 것을 구현해보겠습니다.
v-on
은 Vue.js에서 지원하는 DOM조작하는 이벤트 처리역할을 한다.
v-model
은 양방향 데이터 바인딩을 지원해주는 역할을 한다.
components/todoApp
<template>
<div class="todoApp">
<div class="form-group">
<h1><span class="vue">Vue</span> To-Do
<small>List</small>
</h1>
<form role="form">
<input type="text" class="form-control" placeholder="해야 할 일"
v-model="title"
v-on:keyup.enter="addTodo(title)">
</form>
<button type="button" v-on:click="addTodo(title)" class="btn btn btn-primary">Add</button>
</div>
<div class="todo-list">
<!-- todoList 컴포넌트: v-bind(디렉티브) Element 객체의 속성 동적 데이터 바인딩 -->
<todoList v-bind:todos="todos"></todoList>
</div>
</div>
</template>
<script>
// todoList 컴포넌트 import
import todoList from '@/components/todoList'
export default {
name: 'todoApp',
// data
data(){
return {
title:'',
todos:[
{
title: '운동하기'
},
{
title: 'JAVA'
},
{
title: 'javascript'
},
{
title: '영어'
}
]
}
},
methods:{
addTodo(title){
if(title){
this.todos.push({title:title});
this.title = '';
}
}
},
components: {
'todoList': todoList
}
}
</script>
15. TODO-APP 데이터 삭제
components/todoList.vue
$emit
은 del-todo 부모 TodoApp Component에 이벤트를 내보낸다.
<template>
<div>
<ul v-for="(todo, i) in todos" :key="todos.id" class="list-unstyled">
<li>
`{`{i+1`}`}. `{`{todo.title`}`} <span v-on:click="delTodo(i)" class="close" aria-hidden="true">×</span>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'todoList',
props: ['todos'],
methods: {
// 부모 컴포넌트에서 이벤트 핸들러를 사용하기 위해 정의
delTodo(todo) {
this.$emit('del-todo', todo);
}
}
};
</script>
components/todoList.vue
v-on:del-todo="delTodo"
는 자식 컴포넌트에서 emit한 이벤트를 부모 컴포넌트 처리를 할 수 있다. <todoList v-bind:todos=”todos” v-on:del-todo="delTodo"
></todoList>
<template>
<div class="todoApp">
<div class="form-group">
<h1><span class="vue">Vue</span> To-Do
<small>List</small>
</h1>
<form role="form">
<input type="text" class="form-control" placeholder="해야 할 일"
v-model="title"
v-on:keyup.enter="addTodo(title)">
</form>
<button type="button" v-on:click="addTodo(title)" class="btn btn btn-primary">Add</button>
</div>
<div class="todo-list">
<!-- todoList 컴포넌트: v-bind(디렉티브) Element 객체의 속성 동적 데이터 바인딩 -->
<todoList v-bind:todos="todos" v-on:del-todo="delTodo"></todoList>
</div>
</div>
</template>
우선은 이렇게 Vue를 이용한 todoApp을 만들어봤다.
단순한 todoApp이지만 부모/자식 컴포넌트로 구현한 이유는 테이블, 그리드, 페이징 처리 등 Vue에서 지원하는 Component를 가져다 사용 할 때 그나마 이해가 빠를 수 있다고 생각되서이다.
Vue 에 대해 개념적인 부분과 기술적인 부분 많은 블로그에 포스팅이 되어있고 정보가 많다. 그래서 React, Angular, Vue 등을 안 접해본 개발자분들이 재미를 느끼고 ‘이래서 사용하는구나’, ‘이렇게 사용하구나’가 포커스이기에 사용하는 방법
에 맞춰서 진행하겠습니다.
차후 포스팅은 Restful형태로 약간의 추가작업과 지원하는 테이블, 그리드, 페이징네이션 등을 가져다 사용하는 법을 진행하겠습니다.
참고