vue.js 강의를 들었으니 스스로 만들어보자
우리 팀에서 사용하는 프론트엔드 프레임워크는 vue.js 다. 이 프레임워크를 이용해 모바일웹과 앱 뷰어를 통해, 우리 팀이 관리중인 영역에서의 사용자가 보는 화면을 만들고 있다.
나 또한, 이따금씩 들어오는 프로젝트들로 우리 팀의 vue 앱을 수정하거나 이해해야하는 일들이 생기고 있지만 vue를 제대로 다뤄본적 없는 내 입장에서 쉽지는 않았다. 하지만 조금만 시간을 들여서 이해한다면 충분히 그 데이터의 흐름이나 문법을 이해할 수 있을 정도로 vue는 백엔드 개발자에게 친절한 프레임워크였다.
그래도, 내가 직접 처음부터 시행착오를 겪어보는 것과, 이미 많은 개발자선배들이 구축해놓은 애플리케이션의 일부분을 건드리며 수정하는 것에는 큰 차이가 있다고 생각했다. 그래서 인프런강의도 듣고 책도 보면서 어느정도 vue에 필요한 명령어나 구조를 익혔다.
이론을 학습했으니 이제 스스로 만들어보자. 그래야 개발자니까~!
만드려는 심플 프로젝트는 To-Do List
가장 간단하면서, 즐겁게 입문해볼 수 있는 프로젝트는 todo list 가 아닌가 싶다. 간단한 데이터바인딩과 동작함수만으로 하나의 완성된 기능을 가진 앱을 만들 수 있다. 이 글은 vue의 기본 문법들인 v-지시자들을 구체적으로 설명하지 않는다.
UI 구상
간단한 앱이니만큼 간단한 컴포넌트들로 화면을 구성하도록 할 계획이다. 최상단 Title.vue로 이 앱이 뭔지를 제목으로 알려주고
ToDoInput으로 텍스트 입력을 통해 간단한 todo를 추가할 수 있도록 한다.
하단 넓은 영역을 할일목록으로 두어 자동으로 추가될 수 있도록 한다.
프로젝트 세팅
npm, vue 설치등은 생략.
1. 내가 만들고자 하는 경로에서 vue create <app이름>
2. default3 (vue3+babel)
선택
3. component/HelloWorld.vue
내용을 지우고 title.vue
, ToDoInput.vue
, ToDoList.vue
를 추가한다
// components/Title.vue
<template>
<div id="title">
<h1>{{ name }}</h1>
</div>
</template>
<script>
export default {
name: 'Title',
props: {
name: String
}
}
</script>
<style></style>
vue의 props를 활용해보기 위해 최상위 컴포넌트인 App.vue에서 msg 속성을 전달하도록 한다.
이로서 Title.vue의 h1 tag에는 name 문자열이 출력될 것이다.
npm run serve 명령어를 통해 확인해보자
4. 나머지를 App.vue의 컴포넌트로써 추가하자
// App.vue
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<Title name="TO-DO" />
<to-do-input />
<to-do-list />
</template>
<script>
import Title from './components/Title.vue'
import ToDoInput from './components/ToDoInput.vue'
import ToDoList from './components/ToDoList.vue'
export default {
name: 'App',
components: {
Title,
ToDoInput,
ToDoList
},
data() {
return {
todos: []
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
// components/ToDoInput.vue
<template>
<div id="todoinput">
<input type="text" />
<button type="submit">제출</button>
</div>
</template>
<script>
export default {}
</script>
<style></style>
// components/ToDoList.vue
<template><div id="todolist"></div></template>
<script>
export default {}
</script>
<style></style>
5. 데이터의 흐름을 고민해보자
많은 데이터와 기능이 필요없으므로 위와같이 하면될 것 같다. 부모컴포넌트인 App.vue에서 할일목록 데이터를 가지고 있고
하위 컴포넌트인 TodoInput은 입력된 데이터를 todos에 추가될 수 있도록 전달해주고 ToDoList에서는 데이터의 변화를 감지해 리스트가 자동으로 추가되거나 제거될 수 있게 한다.
그런데 이론적으로 이게 올바른 방식인지는 잘 모르겠다. 누군가 짚어주면 고마울 것 같은데...
6. ToDoList.vue의 기본 구조를 세팅하자
//ToDoList.vue
<template>
<div id="todolist">
<div id="container" v-for="data in todos" :key="data.id">
<li id="text">{{ data }}</li>
</div>
</div>
</template>
<script>
export default {
props: {
todos: []
}
}
</script>
<style></style>
v-for 를 이용해 부모 컴포넌트로부터 전달받은 todos 리스트를 출력한다.
활용된 개념은 props, v-for, v-bind:key 등인데 v-bind의 생략형으로 ':' 를 사용가능하다.
key에 대한 이상적인 값은 각 항목을 식별할 수 있는 고유한 ID 이다.
App.vue의 to-do-list 컴포넌트에 아래와 같이 todos를 전달할 수 있도록 바꾼다.
<to-do-list :todos="todos" />
그리고 테스트할 겸, App.vue의 todos 데이터에 디폴트로 값을 하나 넣어본다.
data() {
return {
todos: ['발 닦기']
}
}
7. 할일을 추가하는 기능을 만들어보자
이번에는 '자식컴포넌트의 데이터와 이벤트를 부모컴포넌트에게 전달' 하는 방법을 이해하기 위함이다.
// components/ToDoInput.vue
<template>
<div id="todoinput">
<input type="text" v-model="content" />
<button type="button" @click="addToDo">제출</button>
</div>
</template>
<script>
export default {
data() {
return {
content: ''
}
},
methods: {
addToDo() {
// emit: 자식컴포넌트에서 부모컴포넌트의 특정 이벤트를 발생시키는 기능
// 1st 파라미터는 지정된 이벤트의 이름
// 2nd 파라미터는 전달하고자하는 데이터의 이름 명시
alert('등록하였습니다')
this.$emit('add-to-do', this.content)
this.content = ''
}
}
}
</script>
<style></style>
입력값의 길이제한과 같은 validation은 생략, v-model을 통해 할일내용을 content에 바인딩하고, button을 클릭시에 addToDo() 메서드가 실행된다. $emit을 통해 부모컴포넌트에 'add-to-do'라는 이름의 이벤트를 전달한다.
주석처럼 두번째 파라미터부터는 전달할 데이터를 기입한다. 이로써 부모컴포넌트는 자식컴포넌트의 data인 content를 받아갈 수 있게 된다.
// App.vue
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<Title name="TO-DO" />
<!-- @<customEvent 이름>="실행되는 method이름" -->
<to-do-input @add-to-do="addToDo" />
<to-do-list :todos="todos" />
</template>
<script>
// ...
data() {
return {
todos: ['발 닦기']
}
},
methods: {
addToDo(content) {
this.todos.push(content)
}
}
}
</script>
<style>
//...
</style>
이제 부모컴포넌트에서는 자식컴포넌트에서 발생하는 add-to-do 이벤트를 받아 addToDo(content) 메서드를 실행할 수 있다. 이 결과로 todos 배열에 content를 추가한다.
그러면 ToDoList에서는 content배열의 변화가 감지될테니 자연스럽게 리스트가 추가될 것으로 예상해볼 수 있다.
결과 확인
8. 원모어띵. 뭔가 불편하다?
웹 이용이 익숙한 사람들은 텍스트를 입력하고 버튼클릭보다는 엔터키를 먼저 누르는 경향이 있다(뇌피셜).
나 또한 그런데,, 지금 여기서는 그게 안된다. 굳이 마우스로 제출 버튼을 눌러야만 등록이 되어야하는걸까?
지금 이 상태로는 쓰기 어렵다. 할일 목록이라기엔 할일 완료나 삭제기능도 없고, UI도 상당히 조잡하다.
그리고 버튼 클릭보다는 엔터키가 동작하는게 더 효율적일 것 같은데
todo list 구실을 하기 위해서는 갈길이 멀다. 그래도 단순히 강의만 보는거보다 스스로 만들어가다보면 더 기억도 오래남고 재밌다.
// ToDoInput.vue
<template>
<div id="todoinput">
<input type="text" v-model="content" @keyup.enter="addToDo" />
<button type="button" @click="addToDo">제출</button>
</div>
</template>
@keyup.enter="addToDo"
가 input 태그에 추가되었다.
위는 v-on:keyup.enter
와 같고 엔터키가 떼지는 순간 이벤트가 동작한다.
이런 간단한 명령 하나 추가하는 것만으로 사용자 경험을 더 높일 수 있을 것 같다.
(정작 내가 일할 때는 이런걸 신경 못쓴다... 기능 제대로 구현하는 것만으로도 힘듬;)
좀 더 완성도가 있게끔 발전시켜나가보자.
다음은 할일 달성 / 삭제 및 날짜 기능을 추가해보자.
'프로그래밍 > frontend' 카테고리의 다른 글
[vue] 스스로 만들어보는 To Do List - 2 : Vuex 적용 (0) | 2021.11.06 |
---|---|
[React] 함수형 컴포넌트로 리액트 표 만들기 (table) (1) | 2020.08.06 |
[React] 리액트로 구구단 웹 페이지를 만들어보자 (0) | 2020.08.02 |