๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿฟ Project

[โ˜•๏ธ๋ธ”๋ž™์ปคํ”ผLv1] TodoList ์ž‘์„ฑ๊ธฐ

by Tamii 2021. 8. 3.
๋ฐ˜์‘ํ˜•

์ง€๊ธˆ๊ป html์— ์ง์ ‘ Web ํ™”๋ฉด์„ ๊ตฌ์„ฑํ–ˆ๋‹ค๋ฉด ์ด์ œ ๊ทธ๋งŒ~~

 

DOM ์— ์ง์ ‘ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ์‹์˜ ํ•œ๊ณ„

 

- DOM์— ์ ‘๊ทผํ•˜๊ณ  ์—…๋ฐ์ดํŠธํ•˜๋Š” ์‹œ์ ์— ๋ช…ํ™•ํ•œ ๊ธฐ์ค€์ ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— UI ๊ฐ€ ๋งŽ์•„์งˆ์ˆ˜๋ก DOM ์—…๋ฐ์ดํŠธ ๊ตฌ๊ฐ„ ์ถ”์ ์ด ์–ด๋ ค์›Œ์ง„๋‹ค.

-  DOM ์— ๋ฟŒ๋ ค์ค„ data๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ์ผ์ผํžˆ ์ฐพ์•„์„œ ์กฐ์ž‘ํ•ด์•ผ ํ•œ๋‹ค.

- ์ค‘๋ณต ์ฝ”๋“œ๊ฐ€ ๋งŽ์•„์ง€๊ณ  DOM ์ ‘๊ทผ์ด ๋งŽ์•„์ง„๋‹ค.

 

๋”ฐ๋ผ์„œ Data๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” component์™€ Data๋ฅผ ๋ฟŒ๋ ค์ค„ component๋ฅผ ๋ถ„๋ฆฌ์‹œํ‚ฌ ํ•„์š”๊ฐ€ ์žˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ๊ธฐ์กด DOM์— ์ง์ ‘ ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ์‹์˜ ์ฝ”๋“œ๋ฅผ ๋ณด๋‹ค ์ปดํฌ๋„ŒํŠธ ํ˜•ํƒœ๋กœ ์ถ”์ƒํ™”ํ•ด๋ณด์ž!

 


๐Ÿ“Œ ์ปดํฌ๋„ŒํŠธ ํ˜•ํƒœ๋กœ ๋ณ€๊ฒฝ

๊ธฐ์กด ์ฝ”๋“œ

<html lang="kr">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Tami - TODOS</title>
    <link rel="stylesheet" href="./src/css/style.css" />
    <script src="./index.js" type="module"></script>
  </head>
  <body>
    <div class="todoapp">
      <h1>TODOS</h1>
      <input
        id="new-todo-title"
        class="new-todo"
        placeholder="ํ• ์ผ์„ ์ถ”๊ฐ€ํ•ด์ฃผ์„ธ์š”"
        autofocus
      />
      <main class="App">
        <input class="toggle-all" type="checkbox" />
        <ul id="todo-list" class="todo-list"></ul>
        <div class="count-container">
          <span class="todo-count">์ด <strong>0</strong> ๊ฐœ</span>
          <ul class="filters">
            <li>
              <a class="all selected" href="#">์ „์ฒด๋ณด๊ธฐ</a>
            </li>
            <li>
              <a class="active" href="#active">ํ•ด์•ผํ•  ์ผ</a>
            </li>
            <li>
              <a class="completed" href="#completed">์™„๋ฃŒํ•œ ์ผ</a>
            </li>
          </ul>
        </div>
      </main>
    </div>
  </body>
</html>

 

 


 

 

์œ„์™€ ๊ฐ™์ธ index.html ์€ index.js ์Šคํฌ๋ฆฝํŠธ๋งŒ ์™ ๊ฑธ์–ด๋‘๊ณ  ๊น”๋”ํ•˜๊ฒŒ ์‚ฌ๋ผ์กŒ๋‹ค!

index.js์—์„œ๋Š” App์„ ๋ถ€๋ฅด๊ณ 

App์—์„œ๋Š” ๋‹ค์–‘ํ•œ component๋ฅผ ๋ถ€๋ฅด๋ฉฐ data๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์—ญํ• ์„ ํ• ๊ฒƒ์ด๋‹ค

TodoList component์™€ ๊ฐ™์€ ๊ฒƒ๋“ค์ด data๋ฅผ ๋ฟŒ๋ ค์ฃผ๋Š” ์—ญํ• ๋งŒ ํ•  ์˜ˆ์ •

 

 

index.html

<head>
	//์ค‘๋žต
    
    <script src="./index.js" type="module"></script>
  </head>
  <body>
    <div class="todoapp">
      <h1>TODOS</h1>
    </div>
  
  </body>
</html>

index.js

import TodoApp from './src/js/TodoApp.js';
new TodoApp(document.querySelector('.todoapp'));

TodoApp

import TodoList from './TodoList.js';

//๊ธฐ๋ณธ์ ์ธ ์ดˆ๊ธฐ ์ƒํƒœ (state)๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Œ
export default function TodoApp($app) {
  this.state = {
    todoes: ['hi', 'hello'],
  };

//์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ๋ณ€๊ฒฝ๋œ state๋ฅผ nextState๋กœ ๋„˜๊ฒจ์คŒ
  this.setState = (nextState) => {
    this.state = nextState;
    todoList.setState(this.state.todoes);
  };
  
  //TodoList ์‹คํ–‰
  const todoList = new TodoList({
    $app,
    initialState: this.state.todoes,
  });
  
  //์ดˆ๊ธฐ ์‹คํ–‰
  const init = () => {
    this.setState({
      ...this.state,
    });
  };
  init();
}

TodoList

export default function TodoList({ $app, initialState }) {
  //$app ์— ๋ฐ›์€ ์ƒํƒœ(inisialState)๋กœ ๋ Œ๋”๋ง ํ•  ์˜ˆ์ •
  this.state = initialState;
  
  //๋ Œ๋”๋งํ•  DOM ์ƒ์„ฑ
  this.$target = document.createElement('ul');
  this.$target.className = 'todo-list';
  $app.appendChild(this.$target);
  
  //state๋ฅผ ๋ฐ›์•„์„œ ํ˜„์žฌ component์˜ state๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‹ค์‹œ ๋ Œ๋”๋งํ•˜๋Š” ํ•จ์ˆ˜
  this.setState = (nextState) => {
    this.state = nextState;
    this.render();
  };
  
  //ํ˜„์žฌ ์ƒํƒœ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ Œ๋”๋ง (todoes์˜ ๋ฐฐ์—ด์„ map์œผ๋กœ li์ƒ์„ฑ)
  this.render = () => {
    const todoTemplate = `${this.state
      .map((todo, idx) => `<li data-index="${idx}">${todo}</div>`)
      .join('')}`;
    this.$target.innerHTML = todoTemplate;
  };
}

 

๐Ÿ“Œ ์ฒดํฌํ•œ todo ์ฒ˜๋ฆฌํ•˜๊ธฐ

this.setState = (nextState) => {
    this.state = nextState;
    this.render();
  };
  this.toggleTodo = (e) => {
    const todoes = this.state;
  };
  this.render = () => {
    const todoTemplate = `${this.state
      .map(
        (todo, idx) =>
          `<li >
          <div class="view">
            <input class="toggle" type="checkbox" />
            <label class="label">${todo}</label>
            <button class="destroy"></button>
          </div>
          <input class="edit " value=${todo}/>
        </li>`
      )
      .join('')}`;
    this.$target.innerHTML = todoTemplate;
  };

addEventListner๋ฅผ ํ•˜๊ธฐ ์œ„ํ•ด์„  ํ˜„์žฌ <input class 'toggle' ~ /> ์„  ๋ณ€์ˆ˜๋กœ ์žก์•„์„œ ํ•ด์•ผ ํ•˜์ง€๋งŒ,

ํ•จ์ˆ˜ ์„ ์–ธ ๋‹น์‹œ์— ์•„์ง ์ฒดํฌ๋ฐ•์Šค๊ฐ€ ๋ Œ๋”๋˜์ง€ ์•Š์•„์„œ ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ์ง€ ๊ณ ๋ฏผํ–ˆ๋‹ค.

 

--> ์ฝ”๋“œ๋ฆฌ๋ทฐ ํ›„ ๋‹ค๋ฅธ ํŒ€์›๋“ค๊ณผ ์–˜๊ธฐํ•ด๋ณด๊ณ  ๋‹ค๋ฅธ ๋ฐฉํ–ฅ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

 

1.  ์ฒดํฌ๋ฐ•์Šค ํด๋ฆญ ์‹œ ํด๋ฆญํ•œ todoli์˜ id ์ „๋‹ฌ

2. ๋ Œ๋”๋ง ์‹œ ํ•ด๋‹น id์ธ ๊ฒฝ์šฐ์—” class ์†์„ฑ ์ถ”๊ฐ€ํ•ด css ๋‹ค๋ฅด๊ฒŒ ์ ์šฉ

 

 

์•„๋ž˜ ๊ทธ๋ฆผ์„ ๋ณด๋ฉด 

e
e.target.className
e.target
e.target.dataset

์ฐจ๋ก€๋กœ ์ด๊ฒƒ๋“ค์„ ์ฐ์–ด ๋ณด์•˜๋Š”๋ฐ

todo list ๋ Œ๋”๋ง ์‹œ data-node-id ๋ผ๋Š” ๊ฐ’์œผ๋กœ idx๋ฅผ ์ œ๊ณตํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—

dataset์„ ํ†ตํ•ด ํ•ด๋‹น ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค

 


๐Ÿ“Œ HTML ์˜ :before ๊ณผ :after ์„ ํƒ์ž

HTML DOM ๊ฐ์ฒด์˜ ๋‚ด๋ถ€์— ์ถ”๊ฐ€์ ์ธ ์ฝ˜ํ…์ธ ๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

:before ์„ ํƒ์ž 

DOM ๊ฐ์ฒด ๋‚ด๋ถ€์˜ ๊ฐ€์žฅ ์•ž์ชฝ์— ์ถ”๊ฐ€

:after ์„ ํƒ์ž 

DOM ๊ฐ์ฒด ๋‚ด๋ถ€์˜ ๊ฐ€์žฅ ๋’ท์ชฝ์— ์ถ”๊ฐ€

.todo-list li .destroy:after {
  content: '×';
}

 

 

 

๋”ฐ๋ผ์„œ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด todo-list์˜ li ๋‚ด๋ถ€ ๊ฐ€์žฅ ๋’ท์ชฝ์— ํ•ญ์ƒ 'X'๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค. 

์ด๋Ÿฌํ—ฅ ์ถ”๊ฐ€ํ•œ ์ฝ˜ํ…์ธ ์—๋Š” ๋…์ž์ ์ธ ์Šคํƒ€์ผ ์†์„ฑ ์ง€์ •์ด ๊ฐ€๋Šฅํ•œ๋ฐ, 

๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” ๋ถ€๋ชจ DOM ์˜ ์†์„ฑ์„ ์ƒ์†๋ฐ›์ง€๋งŒ, ๋‚ด๋ถ€์ ์œผ๋กœ ์ง€์ •ํ•œ ์†์„ฑ์ด ์šฐ์„  ์ ์šฉ๋œ๋‹ค.

:before๊ณผ :after ๋กœ ์ƒ์„ฑ๋œ ์ฝ˜ํ…์ธ ๋Š” default ๊ฐ€ inline์†์„ฑ์ด๋ฏ€๋กœ ํ•ด๋‹น li์™€ ๊ฐ™์€ ์ค„์— ์žˆ๊ฒŒ ํ•˜๊ณ  ์‹ถ์œผ๋ฉด inline-block ์ด๋‚˜ block์œผ๋กœ ์ง€์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

 

 


๐Ÿ“Œ ์‚ฝ์งˆ ๋ชจ์Œ

 

1) ํด๋ฆญํ•œ nodeId ์˜ dataset์€ str์ด๋‹ค 

const deleteTodo = (idx) => {
    const todos = this.state.todoes;
    const newTodos = todos.filter((todo) => {
      console.log('eddddd', idx, todo.idx);
      return todo.idx !== idx;
    });
    console.log(idx);
    console.log('todos', todos);
    console.log('newTodos', newTodos);
    this.setState({
      todoes: newTodos,
    });
  };

์ด๋ ‡๊ฒŒ ์ธ๋ฑ์Šค๋ฅผ ๋น„๊ตํ•ด์„œ ์‚ญ์ œํ•˜๋ ค๋Š”๋ฐ ์•„๋ฌด๋ฆฌ filter๋ฅผ ํ•ด๋„ ์•ˆ๋˜๋Š” ๊ฒƒ์ด๋‹ค? ์ด๊ฒƒ๋•Œ๋ฌธ์— ์˜ค๋žœ์‹œ๊ฐ„์„ ์‚ฝ์งˆํ–ˆ์ง€๋ฉด ๊ฒฐ๋ก ์€ ๋‘๊ฐœ์˜ type์ด ๋‹ฌ๋ผ์„œ์˜€๋‹ค.....

 

 

 

 

 const $node = e.target;
    const $viewnode = e.target.closest('.view');
    const { nodeId } = $viewnode.dataset;

    if ($node.className == 'destroy') {
      this.deleteTodoItem(nodeId);

์ด๋Ÿฐ์‹์œผ๋กœ nodeId๋ฅผ dataset์œผ๋กœ ๋„ฃ์–ด์ฃผ๊ณ  ์žˆ์—ˆ๋Š”๋ฐ, ์ด๋ ‡๊ฒŒ ๋„ฃ์œผ๋ฉด nodeId์˜ ํƒ€์ž…์ด string์ด๋ผ๋Š” ์ ์ด๋‹ค!!!!!

์ดํ† ๋ก ๊ฐ„๋‹จํ•œ ์ž‘์—…์„!!!!! ์›ƒ๊ธด๊ฑด TodoList addํ• ๋•Œ๋„ ์ด ๋ฌธ์ œ๋•Œ๋ฌธ์— parseInt ํ•ด๋†จ๋Š”๋ฐ ๋‚˜์ค‘์„ ์ƒ๊ฐ ์•ˆํ•˜๊ณ  ์ง€์—ฝ์ ์ธ ๋ถ€๋ถ„์— ํ•ด๋†“์•˜๋”๋‹ˆ ๋˜ ๋˜‘๊ฐ™์€ ๋ฌธ์ œ์— ๊ฑธ๋ ธ๋˜ ๊ฒƒ์ด๋‹ค. ์•ž์œผ๋กœ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ ์ด๋Ÿฐ ๋ถ€๋ถ„์€ ์ฃผ์˜ํ•ด์•ผ ๊ฒ ๋‹ค.

 


2) template literal ์‹œ ์†์„ฑ์€ str์œผ๋กœ!

 

์ดˆ๊ธฐ ์ฝ”๋“œ 

     <li  class="${todo.state === 'completed' ? 'completed' : ''} ${
            todo.state === 'editing' ? 'editing' : ''
          }">
          <div class="view" data-node-id=${todo.idx} >
            <input class="toggle" type="checkbox" />
            <label class="label">${todo.content}</label>
            <button class="destroy"></button>
          </div>
          <input class="edit" value=${todo.content}/>
        </li>

input ๊ณผ lebel ์— ๋™์ผํ•˜๊ฒŒ todo.content ๋ฅผ ๋„ฃ์–ด์คซ๋Š”๋ฐ

input ์˜ value์—” ์ž๊พธ๋งŒ ๋„์–ด์“ฐ๊ธฐ๊ฐ€ ์ œ์™ธ๋˜๋Š”๊ฒƒ์ด๋‹ค?

 

๋ฌธ์ œ๋Š” ๋ฐ”๋กœ input์˜ vlaue๋ฅผ str์œผ๋กœ ๋„˜๊ฒจ์ฃผ์ง€ ์•Š์€ ๊ฒƒ!

 

<input class="edit" value="${todo.content}"/>

ํ•ด๋‹น๋ถ€๋ถ„์„ ์ด๋ ‡๊ฒŒ ๋ฌธ์ž์—ด๋กœ ๋ฐ”๊ฟ”์ฃผ๋ฉด์„œ ์ •์ƒ ์ž‘๋™.

 

 

์ •๋ง ์‚ฌ์†Œํ•œ ์‹ค์ˆ˜์˜€๋Š”๋ฐ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ด์„œ ๋” ๋ชป์ฐพ์•˜๋‹ค...

 

 

 


 

๐Ÿ“Œ Refactoring 

์Šคํ”ผ๋“œํ•œ ๊ตฌํ˜„์„ ํ•˜๋‹ค๋ณด๋‹ˆ component๋งˆ๋‹ค ํ•จ์ˆ˜๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์œ„์น˜๊ฐ€ ๋‹ฌ๋ผ์„œ ์ •๋ฆฌ๊ฐ€ ํ•„์š”ํ–ˆ๋‹ค.

๊ธฐ๋ณธ์ ์ธ ํ‹€์„ ๋ณด๋ฉด TodoApp์—์„œ onToggle์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ๋‹ค ๊ตฌํ˜„ํ•˜๊ณ  TodoList์—์„œ๋Š” ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ตฌ์กฐ์ธ๋ฐ๋ฐ

๋…ธ๋“œ์˜ ์ด๋ฒคํŠธ( $node addEventListener ) ๊ฐ€ ํ•œ๋ˆˆ์— ๋ณด์ด๊ฒŒํ•˜๊ธฐ ์œ„ํ•ด ๋”ฐ๋กœ ํ•จ์ˆ˜๋กœ ( this.toggleTodoItem) ๋ถ„๋ฆฌํ–ˆ์ง€๋งŒ 

๋…ธ๋“œ์˜ ์ด๋ฒคํŠธ ์•ˆ์—์„œ ๋กœ์ง์„ ๋‹ค์ฒ˜๋ฆฌํ•ด ๋ฒ„๋ ค์„œ ๋ถ„๋ฆฌํ•œ ํ•จ์ˆ˜๋Š” ์˜๋ฏธ๊ฐ€ ์—†์–ด์กŒ๋‹ค.

 

์•„๋ž˜์ฒ˜๋Ÿผ ํด๋ฆญ ์ด๋ฒคํŠธ๊ฐ€ ํ•˜๋‚˜๋ฉด ์ƒ๊ด€ ์—†์ง€๋งŒ 

ํด๋ฆญํ•œ ๋…ธ๋“œ์— ๋”ฐ๋ผ์„œ 

 

์ด์ „ ์ฝ”๋“œ

//๋…ธ๋“œ์˜ ์ด๋ฒคํŠธ
$nodeTodoList.addEventListener('click', (e) => {

    const $node = e.target;
    
    if ($node.className === 'toggle') {
      const { nodeId } = $node.closest('.view').parentNode.dataset;
      this.toggleTodoItem(parseInt(nodeId));
    } 
    //์ค‘๋žต



//๋”ฐ๋กœ ๋ถ„๋ฆฌํ•œ ํ•จ์ˆ˜
this.toggleTodoItem = (nodeId) => {

    onToggle(parseInt(nodeId));
  };

์•„๋ž˜์™€ ๊ฐ™์ด ํด๋ฆญ ์ด๋ฒคํŠธ๊ฐ€ ๋งŽ์•„์ง€๋ฉด ๋ณต์žกํ•ด์ง„๋‹ค.

 $nodeTodoList.addEventListener('click', (e) => {
    const $node = e.target;
    
    // ์ฒดํฌ๋ฐ•์Šค ํด๋ฆญ ์‹œ
    if ($node.className === 'toggle') {
    
    }
    // ์‚ญ์ œ ํด๋ฆญ ์‹œ
    if ($node.className === 'destroy') {

    }
    // ํŽธ์ง‘ ํด๋ฆญ ์‹œ
    if ($node.className === 'edit') {

    }
  });

 

 

๊ฐœ์„  ์ฝ”๋“œ!

// ๋…ธ๋“œ์˜ ์ด๋ฒคํŠธ
$nodeTodoList.addEventListener('click', (e) => {
    const $node = e.target;

    if ($node.className === 'toggle') {
      this.toggleTodoItem($node);
    }
    if ($node.className === 'destroy') {
      this.deleteTodoItem($node);
    }

    if ($node.className === 'edit') {
      this.editTodoItem($node);
    }
  });


// ๋”ฐ๋กœ ๋ถ„๋ฆฌํ•œ ํ•จ์ˆ˜
this.toggleTodoItem = ($node) => {
    const { nodeId } = $node.closest('.view').parentNode.dataset;
    onToggle(parseInt(nodeId));
  };

  this.deleteTodoItem = ($node) => {
    const { nodeId } = $node.closest('.view').parentNode.dataset;
    onDelete(parseInt(nodeId));
  };

  this.editTodoItem = ($node) => {
    if ($node.className === 'edit') {
      const { nodeId } = $node.parentNode.dataset;
      $node.addEventListener('keydown', (e) => {
        //Enter key ์ž…๋ ฅ
        if (e.keyCode === 13) {
          onEdit(parseInt(nodeId), true, $node.value);
        } //esc key ์ž…๋ ฅ
        else if (e.keyCode === 27) {
          onEdit(parseInt(nodeId), false, '');
        }
      });
    } else {
      const { nodeId } = $node.closest('.view').parentNode.dataset;
      if ($node.className === 'label') {
        onEdit(parseInt(nodeId), false, '');
      }
    }
  };

์ด๋ ‡๊ฒŒ ๋ถ„๋ฆฌํ•จ์œผ๋กœ์จ ํด๋ฆญ ์ด๋ฒคํŠธ๊ฐ€ ์ผ์–ด๋‚ฌ์„ ๋• ์–ด๋–ค ํ•จ์ˆ˜๋“ค์ด ์“ฐ์ด๋Š”์ง€ ํ•œ๋ˆˆ์— ๋ณด์ด๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

 


๐Ÿ“Œ filter ๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ์ƒํƒœ๊ด€๋ฆฌ ๊ณต์‚ฌ

์ฒ˜์Œ filter๋ฅผ ๊ตฌํ˜„ํ•  ๋• ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋กœ์ง์œผ๋กœ ์ƒ๊ฐํ–ˆ๋‹ค.

1) ๊ฐ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ todo ๋ฐ์ดํ„ฐ maping

2) todo data ๊ต์ฒด

 

๊ทธ๋Ÿฌ๋‹ค ํ•„ํ„ฐ๋ง ํ•œ data์™€ ์›๋ณธ data๋ฅผ ํ•œ ๊ณณ์—์„œ ๊ด€๋ฆฌํ•  ์ˆ˜ ์—†์—ˆ๋‹ค. 

์›๋ณธ data๊ฐ€ ํ•„ํ„ฐ๋ง ๋˜๋ฉด์„œ ๊ธฐ์กด data๊ฐ€ ๋‚ ๋ผ๊ฐ€๋Š” ๋Œ€๋ถˆ์ƒ์‚ฌ๊ฐ€ ์ผ์–ด๋‚˜๊ณ .. 

์ด ํˆฌ๋‘๋ฆฌ์ŠคํŠธ๋Š” ํ•œ๋ฒˆ ์™„๋ฃŒ์•ˆํ•œ ์ผ์ด ๋ญ”์ง€ ํ™•์ธํ•˜๋ฉด ์™„๋ฃŒํ•œ ์ผ์ด ์˜์˜ ์‚ฌ๋ผ์ ธ ๋ชป๋ณด๊ฒŒ ๋˜๋Š” ํœ˜๋ฐœ์„ฑ todolist๊ฐ€ ๋˜๋ฒ„๋ฆฐ๋‹ค.^^

 

 

์ฒ˜์Œ ์ฝ”๋“œ (ํœ˜๋ฐœ์„ฑ)

const filterTodo = (filterType) => {
    const todos = this.state.todoes;
    const tempTodos = todos.slice();
    
    //์ „์ฒด๋ณด๊ธฐ
    if (filterType === 'all selected') {
      this.setState({ todoes: todos });
      
    } 
    
    // ์™„๋ฃŒํ•œ ์ผ
    else if (filterType === 'completed') {
      const completedTodos = tempTodos.filter(
        (todo) => todo.state === 'completed'
      );
      this.setState({
        todoes: completedTodos,
      });
    } 
    
    //ํ•ด์•ผํ•  ์ผ
    else if (filterType === 'active') {
      const decompletedTodos = tempTodos.filter(
        (todo) => todo.state !== 'completed'
      );
      this.setState({
        todoes: decompletedTodos,
      });
    }
  };

์ด๋ ‡๊ฒŒ ์„ธ๊ฐ€์ง€ ์ผ๋“ค์ด ๋ฒŒ์–ด์งˆ ๋•Œ์˜ ์ƒํƒœ๋ฅผ ํ•œ ๊ณณ์—์„œ ๋ณด๊ด€ํ•œ ๊ฒฐ๊ณผ 

ํ•œ๋ฒˆ ํ•„ํ„ฐ๋ง์„ ํ•˜๋ฉด ์›๋ณธ ๋ฐ์ดํ„ฐ๋Š” ์‚ฌ๋ผ์ง„๋‹ค..^^

 

 

๋”ฐ๋ผ์„œ ๋‚˜๋Š” isFilter์™€ ๊ฐ™์€ flag ์กด์žฌ๋ฅผ ๋งŒ๋“ค์–ด์„œ

isFilter === true ์ด๋ฉด  ํ•„ํ„ฐ๋ง ๋œ ๊ฒฐ๊ณผ๋ฅผ ๋ Œ๋”๋ง

isFilter === false ๋ผ๋ฉด ์›๋ณธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ Œ๋”๋ง

ํ•˜๋„๋ก ๋ณ€๊ฒฝํ•˜๊ธฐ๋กœ ๊ฒฐ์‹ฌํ–ˆ๋‹ค.

 

 


๐Ÿ“Œ ๊ฐœ์„ ์„ ์œ„ํ•œ ๋…ธ๋ ฅ

1) ๋ฉ”์„ธ์ง€ ๋ฐ class data  const ๋กœ ๋ถ„๋ฆฌ

export const FILTER_TYPES = {
  ALL: 'FILTER_TYPES.ALL',
  COMPLETE: 'completed',
  ACTIVE: 'active',
};

export const TODO_ITEM_CLASS = {
  TOGGLE: 'toggle',
  DESTROY: 'destroy',
  EDIT: 'edit',
  LABEL: 'label',
  VIEW: 'view',
};

export const TODO_FILTER_MENU = {
  ALL_MENU: '์ „์ฒด๋ณด๊ธฐ',
  ACTIVE_MENU: 'ํ•ด์•ผํ•  ์ผ',
  COMPLETE_MENU: '์™„๋ฃŒํ•œ ์ผ',
};

๊ธฐ์กด ์ฝ”๋“œ

  $nodeTodoList.addEventListener('click', (e) => {
    const $node = e.target;

    if ($node.className === 'toggle') {
      this.toggleTodoItem($node);
    }
    if ($node.className === 'destroy') {
      this.deleteTodoItem($node);
    }

    if ($node.className === 'edit') {
      this.editTodoItem($node);
    }
  });

๋ณ€๊ฒฝ ์ฝ”๋“œ

  $nodeTodoList.addEventListener('click', (e) => {
    const $node = e.target;

    if ($node.className === TODO_ITEM_CLASS.TOGGLE) {
      this.toggleTodoItem($node);
    }
    if ($node.className === TODO_ITEM_CLASS.DESTROY) {
      this.deleteTodoItem($node);
    }

    if ($node.className === TODO_ITEM_CLASS.EDIT) {
      this.editTodoItem($node);
    }
  });

๋ฉ”์„ธ์ง€์™€ class ๋ฐ์ดํ„ฐ๋Š” const์—์„œ ํ•œ๋ฒˆ์— ๊ด€๋ฆฌํ•˜์—ฌ ๋ณ€๊ฒฝ์ด ์ผ์–ด๋‚  ์‹œ ๋™์‹œ์— ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋„๋ก ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์‰ฝ๊ฒŒ ๋ณ€๊ฒฝํ–ˆ๋‹ค.


๐Ÿ“Œ  localStorage ์ ์šฉํ•ด๋ณด๊ธฐ

์ฒ˜์Œ localStorage๋ฅผ ๋„์ž…ํ–ˆ์„ ๋•Œ, TodoApp์ด ์ƒ์„ฑ๋˜๊ธฐ ์ „์— localStorage๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค.

 

TodoApp

export default function TodoApp($app) {
  // localStorage.clear();

  const initialDtate = {
    todoes: [
      {
        idx: 0,
        content: 'hiEvery One',
        state: '',
      },
      {
        idx: 1,
        content: 'Im Tami',
        state: '',
      },
    ],
    todoesFiltered: [],
    filterState: FILTER_TYPES.ALL,
    todoesCount: '0',
  };
  const localData = JSON.parse(localStorage.getItem('state'));
  const viewData = localData ? localData : initialDtate;
  this.state = viewData;

์ด๋ ‡๊ฒŒ TodoApp๋‚ด๋ถ€์—์„œ localStorage๋ฅผ ์ฒ˜์Œ ๊ฐ€์ ธ์˜ด์œผ๋กœ์จ ํ•ด๊ฒฐํ–ˆ๋‹ค.

 

 

 

localStorage ์„ฑ๊ณต!!

local์˜ this.state๋กœ๋งŒ ๊ด€๋ฆฌํ•˜๋˜ ๋ฐ์ดํ„ฐ๋Š” ์ƒˆ๋กœ๊ณ ์นจ ํ›„์—” ์‚ฌ๋ผ์กŒ์ง€๋งŒ

localStorage๋กœ ๊ด€๋ฆฌํ•จ์œผ๋กœ์จ ์ƒˆ๋กœ๊ณ ์นจํ•ด๋„์‚ฌ๋ผ์ง€์ง€ ์•Š๊ฒŒ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ด์กŒ๋‹ค.!!

 

 

 

 

 

 

๋Œ“๊ธ€