11. Todo - Create

간단한 Todo App 을 만들어봅니다.

목표

List State 에 새로운 Todo 를 생성합니다.

실습

추가될 Todo State 는 아래와 같습니다.

{
  id: new Date().getTime(), // 고유한 값을 주기 위해 Date 를 이용합니다.
  text: '블라블라' 
  isDone: false 
}

데이터 추가는 Header 의 Input 에 의해서 일어나게됩니다. 하지만 모든 데이터를 가지고 있는 곳은 App.vue 이기 때문에 List 에 새로운 Todo 를 추가하기 위한 함수는 App.vue 에 위치하게됩니다.

함수들은 methods 라는 곳 안에 위치하게 됩니다.

methods: {}

Todo 를 추가하기 위한 함수를 만들어보겠습니다.

// App.vue 

export default {
  // ...
  methods: {
    insertTodo(text) {
      this.todos = [
        ...this.todos, // 기존의 배열에 새로운 todo 를 추가합니다.
         {
          // id, isDone 의 경우 같은 포맷을 유지하기 때문에 새로 받지 않습니다. 
          id: new Date().getTime(), 
          text, // 유동적인 text 값만 받습니다.
          isDone: false
        }
      ];
    }
  }
};

insertTodo 함수에 전달되는 text 값은 header 에 있는 input 의 value 값 입니다. 부모와 자식사이에 이벤트를 이용하여 데이터를 주고 받을 수 있어야 합니다.

이때 필요한 개념이 on, emit 입니다. 부모는 on 을 이용하여 event 를 등록하고 자식은 emit 을 이용하여 해당 이벤트를 발생시킵니다.

Header.vue 가 자식 App.vue 가 부모의 개념입니다.

<template>
  <div id="app">
    <section class="todoapp">
      <Header @insertTodo="insertTodo" />
      <Todo :todos="todos" />
      <Footer />
    </section>
  </div>
</template>

@insertTodo 라는 custom event 를 등록을 해줍니다.

Header.vue 에서는 input 의 value 를 v-model 을 사용하여 양방향 데이터바인딩을 이용합니다.

<template>
  <header class="header">
    <h1>todos</h1>
    <input
      class="new-todo"
      v-model="text"
      autofocus
      autocomplete="off"
      placeholder="What needs to be done?"
    />
  </header>
</template>

<script>
export default {
  data() {
    return {
      text: ""
    };
  }
};
</script>

v-model 을 이용하면 input 의 value 가 바뀔때 text state 를 변경하게됩니다. 그 변경된 값은 다시 input의 value 가 됩니다. 이것이 양방향 데이터 바인딩인데 따로 input 에 event 를 걸어 state 를 업데이트하지 않아도 되기 때문에 편하게 사용 할 수 있습니다.

input에 값을 변경하면 저절로 text 의 값이 변경되는걸 볼 수 있습니다. 우리는 이 text 값을 이용하여 todo 를 생성할겁니다.

input 에 keypress event 를 걸어줘서 enter 가 눌렸을 때를 캐치하고자합니다. 각 키에는 고유한 숫자가 부여됩니다. enter 는 13입니다. 입력한 key 가 13일때 text 값을 부모가 등록해준 event 를 이용하여 넘겨줍니다. 그 후 text 값을 비워줍니다.

<template>
  <header class="header">
    <h1>todos</h1>
    <input
      class="new-todo"
      autofocus
      autocomplete="off"
      placeholder="What needs to be done?"
      v-model="text"
      @keypress="handleTodo"
    />
  </header>
</template>

<script>
export default {
  data() {
    return {
      text: ""
    };
  },
  methods: {
    handleTodo({ keyCode }) {
      const { text } = this;

      if (keyCode === 13 && text !== "") {
        this.$emit("insertTodo", text);
        this.text = "";
      }
    }
  }
};
</script>

간단하게 todo 를 추가했습니다.

Last updated