8. Todo App 개선 - 할 일 목록 표시

freejia·2021년 10월 24일
0

캡틴판교님의 Vue.js 중급 강좌 - 웹앱 제작으로 배워보는 Vue.js, ES6, Vuex강의를 정리했습니다.
매일 20분 야금야금 Vue.js 중급 화이팅.

IDE: Visual Studio Code
크롬 뷰 개발자 도구: Vue.js devtools


현재 앱 구조의 문제점

할 일을 추가/삭제 할 때, localStorage의 상태가 화면에 즉시 반영되지 않는다.

컴포넌트 간에 데이터 통신이 필요하다.

개선된 앱 구조

로컬 스토리지의 todoItems를 App컴포넌트의 todoItems로 동기화한다.
할일 목록 todoItems를 App 컴포넌트가 알고 있다.
App을 컨테이너라고 보자.

props와 event emit

TodoList는 propsdata로 todoItems 데이터를 내려받는다.
TodoInput컴포넌트는 추가 이벤트, TodoFooter는 삭제 이벤트를 App으로 올린다.

개선할 사항

  1. 할 일 목록 표시 : todoItems 배열을 App에서 관리하자
  2. 할 일 추가 : event emit으로 TodoList의 데이터를 App으로 올리기.
  3. 할 일 삭제
  4. 할 일 완료
  5. 할 일 모두 삭제

할 일 목록 표시 개선하기

  1. todoItems 배열을 App.vue에서 관리하도록 하자.
  2. App.vue의 배열 데이터를 TodoList.vue로 내린다. (props속성 이용)

1. TodoList의 todoItems 배열을 App컴포넌트로 옮긴다.

[App.vue]의 todoItems로 관리되게 한다.

data에 배열 todoItems를 만든다.

export default {

  data: function(){
    return {
      todoItems: []
    }
  },

localStorage의 데이터를 todoItems 배열에 담는 created 속성

TodoList.vue에 정의한 created 속성을 App.vue로 그대로 옮기자.
이제 App.vue가 생성될 때 localStorage의 데이터를 todoItems배열에 담아서 갖고 있는다.

created: function(){
    if (localStorage.length > 0) {
      for(var i = 0; i< localStorage.length; i++){
        if (localStorage.key(i) !== 'loglevel:webpack-dev-server') {
          this.todoItems.push(JSON.parse(localStorage.getItem(localStorage.key(i))));
        }
      }
    }
  }

2. App의 todoItems배열을 TodoList 컴포넌트로 내린다

App.vue의 todoItems 배열을 propsdata로 하위 컴포넌트 TodoList에 내리기 위해 v-bind 해준다.

v-bind로 하위 props속성을 App.vue의 propsdata와 연결한다.

App.vue의 template에는 컴포넌트 4개를 포함한다.
TodoList컴포넌트에 props속성을 연결한다.

<template>
  <div id="app">
    <TodoHeader></TodoHeader>
    <TodoInput></TodoInput>
    <TodoList v-bind:propsdata="todoItems"></TodoList>
    <TodoFooter></TodoFooter>
  </div>
</template>

이렇게 App.vue의 template에 propsdata를 연결하면,
배열 데이터가 propsdata라는 이름의 props속성으로 내려간다.

TodoList.vue에 propsdata라는 props 속성을 만들고,

export default {
  props: ['propsdata'],

목록 출력 for문에서는 propsdata에서 데이터를 꺼내자.

<li v-for="(todoItem, index) in propsdata" v-bind:key="todoItem.item" class="shadow">
        <i class="checkBtn fas fa-check" v-bind:class="{checkBtnCompleted: todoItem.completed}" 

할 일 추가 기능 개선하기

TodoInput에서 입력한 값을 상위 컴포넌트인 App으로 올리자.

event emit 다시 복습 : 이벤트명과 메서드명을 바인딩한다.

하위 컴포넌트의 이벤트를 상위 컴포넌트의 메서드로 연결하기
v-on:하위 컴포넌트의 이벤트 명="현재 컴포넌트의 메서드 명"

1. TodoInput에서 입력한 값을 상위 컴포넌트인 App으로 올리기.

TodoInput에서 값을 추가하면, addTodo 메서드가 동작한다.

    addTodo: function(){
      if (this.newTodoItem !== ''){
        this.$emit('addTodoItem', this.newTodoItem);
        this.clearInput();
      }
    },

중요: addTodoItem이름의 emit을 정의하고 인자로 newTodoItem입력값을 넘긴다.

this.$emit('addTodoItem', this.newTodoItem);

2. App.vue의 template에서 하위 이벤트명과 메서드 바인딩

하위 이벤트명 'addTodoItem'이 올라오면, App.vue의 메서드 addOneItem이 동작한다.

<TodoInput v-on:addTodoItem="addOneItem"></TodoInput>

App.vue의 template 코드

<template>
  <div id="app">
    <TodoHeader></TodoHeader>
    <TodoInput v-on:addTodoItem="addOneItem"></TodoInput>
    <TodoList v-bind:propsdata="todoItems"></TodoList>
    <TodoFooter></TodoFooter>
  </div>
</template>

3. App.vue의 addOneItem메서드에서는 배열 값을 갱신한다

addOneItem의 인자 todoItem은 emit이벤트에서 올려준 데이터다.
todoItem을 todoItems배열에 추가한다.

    addOneItem: function(todoItem){
      var obj = {completed: false, item: todoItem}
      localStorage.setItem(todoItem, JSON.stringify(obj));
      this.todoItems.push(obj);
    }

TodoList.vue의 emit 정의 : this.newTodoItem를 인자로 올려줬다.

this.$emit('addTodoItem', this.newTodoItem);

할 일을 추가하면 목록에 즉시 반영된다


다음 시간에는 할 일을 삭제하는 기능을 개선해본다.

profile
코딩 리딩 라이딩💛

0개의 댓글