ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 코딩 자율학습단(Vue.js 프런트엔드 개발 입문) 8일차
    정보교육/프런트엔드 2024. 6. 27. 12:31

    6장 실습: 할 일 관리 앱 만들기

    o 할 일 관리 앱의 ui 구성

    HTML 코드 작성, css 코드 작성, 컴포넌트 분리

    o 할 일 관리 앱의 기능 구현

    - 할 일 목록 입력받기

    데이터 정의, v-model 디렉티브로 입력창과 양방향 데이터 바인딩

    버튼 클릭이나 엔터를 통해 사용자가 어떤 값을 입력했는지 확인 이벤트 등록

    입력한 값을 부모 컴포넌트로 전달

    - 할 일 목록 필터링하기

    할 일 목록을 '전체'와 '완료'로 필터링

    current 데이터를 초기값으로 'all' updateTab을 이용해서 이벤트 발신

    filter를 통해서 completed라면 속성 값이 true인 것만 보여줌. 

    - 할 일 목록 출력하기

    computedTodo 데이터를 props 옵션 속성으로 받는다.

    배열이므로 v-for 데릭티브로 할 일 목록을 반복

    delete, update 함수 연결

    // App.vue
    
    <script>
    import TodoHeader from "@/components/TodoHeader.vue";
    import TodoList from "@/components/TodoList.vue";
    import TodoInput from "@/components/TodoInput.vue";
    export default {
      components: {
        TodoHeader,
        TodoList,
        TodoInput,
      },
      data() {
        return {
          todo: [],
          current: "all",
        };
      },
      computed: {
        computedTodo() {
          if (this.current === "all") {
            return this.todo;
          } else {
            return this.todo.filter((v) => v.completed);
          }
        },
      },
      methods: {
        addTodo(inputMsg) {
          const item = {
            id: Math.random(), // 고유한 값
            msg: inputMsg, // 할 일 텍스트
            completed: false, // 할 일 완료 여부
          };
          this.todo.push(item);
        },
        updateTab(tab) {
          this.current = tab;
        },
        deleteTodo(id) {
          this.todo = this.todo.filter((v) => v.id !== id);
        },
        updateTodo(id) {
          this.todo = this.todo.map((v) =>
            v.id === id ? { ...v, completed: !v.completed } : v
          );
        },
      },
    };
    </script>
    <template>
      <div class="todo">
        <TodoHeader :current @update-tab="updateTab" />
        <TodoList
          :computed-todo="computedTodo"
          @delete-todo="deleteTodo"
          @update-todo="updateTodo"
        />
        <TodoInput @add-todo="addTodo" />
      </div>
    </template>
    // TodoHeader.vue
    
    <script>
    export default {
      props: {
        current: {
          type: String,
          default() {
            return "all";
          },
        },
      },
      emits: ["update-tab"],
      methods: {
        updateTab(tab) {
          this.$emit("update-tab", tab);
        },
      },
    };
    </script>
    
    <template>
      <div class="todo__title">
        <h1 class="todo__text">Todo List</h1>
        <ul class="todo__tab">
          <li
            :class="{ 'todo__tab--active': current === 'all' }"
            @click="updateTab('all')"
          >
            전체
          </li>
          <li
            :class="{ 'todo__tab--active': current === 'completed' }"
            @click="updateTab('completed')"
          >
            완료
          </li>
        </ul>
      </div>
    </template>
    // TodoInput.vue
    
    <script>
    export default {
      data() {
        return {
          inputMsg: "", // 데이터 정의
        };
      },
      emits: ["addTodo"],
      methods: {
        addTodo() {
          this.$emit("addTodo", this.inputMsg); // 부모 컴포넌트 이벤트 호출
          this.inputMsg = ""; // 입력 데이터 초기화
        },
      },
    };
    </script>
    <template>
      <div class="todo__input">
        <input
          v-model="inputMsg"
          type="text"
          class="todo__input-text"
          placeholder="할 일을 입력하세요."
          @keydown.enter="addTodo"
        />
        <button class="todo__input-btn" @click="addTodo">등록</button>
      </div>
    </template>
    // TodoList.vue
    
    <script>
    export default {
      props: {
        computedTodo: {
          type: Array,
          default() {
            return [];
          },
        },
      },
      methods: {
        deleteTodo(id) {
          this.$emit("delete-todo", id);
        },
        updateTodo(id) {
          this.$emit("update-todo", id);
        },
      },
    };
    </script>
    <template>
      <div class="todo__list">
        <div
          v-for="item in computedTodo"
          :key="item.id"
          class="todo__item"
          :class="{ 'todo__item--completed': item.completed }"
        >
          <input
            type="checkbox"
            :id="`chk${item.id.toString()}`"
            :checked="item.completed"
            @click="updateTodo(item.id)"
          />
          <label
            :for="`chk${item.id.toString()}`"
            class="todo__checkbox-label"
          ></label>
          <span class="todo__item-text">{{ item.msg }}</span>
          <span
            class="material-symbols-outlined todo__delete-icon"
            @click="deleteTodo(item.id)"
            >delete</span
          >
        </div>
        <div v-if="computedTodo.length === 0" class="todo__item--no">
          <p>할 일이 없습니다.</p>
        </div>
      </div>
    </template>
Designed by Tistory.