🤖

JavaScript PrimerのTodoアプリ作成でJS復習(アイテムの更新、削除)

2023/12/31に公開

記事概要

JSの復習として、JavaScript PrimerのTodoアプリ作成をやってみて、結構いい復習になったので紹介
https://jsprimer.net/

この続き
https://zenn.dev/runnaoya/articles/a2c35c74e4b61b
https://zenn.dev/runnaoya/articles/e788979c8635fc

対象読者

JavaScriptの基本的な構文は知っている初学者向けです。

復習内容

アイテムの更新

チェックボックスを押すと以下のように状態が変わる

  • App.js
    チェックボックスにチェックがついたとき、inputCheckboxElement.addEventListenerが発火する。
export class App {
    // 1. TodoListModelの初期化
    #todoListModel = new TodoListModel();

    mount() {
        const formElement = document.querySelector("#js-form");
        const inputElement = document.querySelector("#js-form-input");
        const containerElement = document.querySelector("#js-todo-list");
        const todoItemCountElement = document.querySelector("#js-todo-count");
        // 2. TodoListModelの状態が更新されたら表示を更新する
        this.#todoListModel.onChange(() => {
          const todoListElement = element`<ul></ul>`;
          const todoItems = this.#todoListModel.getTodoItems();
          todoItems.forEach(item => {
              // 完了済みならchecked属性をつけ、未完了ならchecked属性を外す
              const todoItemElement = item.completed
                  ? element`<li><input type="checkbox" class="checkbox" checked><s>${item.title}</s></li>`
                  : element`<li><input type="checkbox" class="checkbox">${item.title}</li>`;
              // チェックボックスがトグルしたときのイベントにリスナー関数を登録
              const inputCheckboxElement = todoItemElement.querySelector(".checkbox");
              inputCheckboxElement.addEventListener("change", () => {
                  // 指定したTodoアイテムの完了状態を反転させる
                  this.#todoListModel.updateTodo({
                      id: item.id,
                      completed: !item.completed
                  });
              });
              todoListElement.appendChild(todoItemElement);
          });
          render(todoListElement, containerElement);
          todoItemCountElement.textContent = `Todoアイテム数: ${this.#todoListModel.getTotalCount()}`;
        })
  • TodoListModel.js
    ここでcompletedを更新している
    /**
     * 指定したidのTodoItemのcompletedを更新する
     * @param {{ id:number, completed: boolean }}
     */
    updateTodo({ id, completed }) {
      // `id`が一致するTodoItemを見つけ、あるなら完了状態の値を更新する
      const todoItem = this.#items.find(todo => todo.id === id);
      if (!todoItem) {
          return;
      }
      todoItem.completed = completed;
      this.emitChange();
  }

アイテムの削除

xを押すと非同期でアイテムが削除される

  • App.js
    elementに削除ボタン(x)を追加。
    削除ボタン(x)が押された時の処理を追記
export class App {
    // 1. TodoListModelの初期化
    #todoListModel = new TodoListModel();

    mount() {
        const formElement = document.querySelector("#js-form");
        const inputElement = document.querySelector("#js-form-input");
        const containerElement = document.querySelector("#js-todo-list");
        const todoItemCountElement = document.querySelector("#js-todo-count");
        // 2. TodoListModelの状態が更新されたら表示を更新する
        this.#todoListModel.onChange(() => {
          const todoListElement = element`<ul></ul>`;
          const todoItems = this.#todoListModel.getTodoItems();
          todoItems.forEach(item => {
              // 削除ボタン(x)をそれぞれ追加する
              const todoItemElement = item.completed
                  ? element`<li><input type="checkbox" class="checkbox" checked>
                      <s>${item.title}</s>
                      <button class="delete">x</button>
                  </li>`
                  : element`<li><input type="checkbox" class="checkbox">
                      ${item.title}
                      <button class="delete">x</button>
                  </li>`;
              // 略
	      
              // 削除ボタン(x)がクリックされたときにTodoListModelからアイテムを削除する
              const deleteButtonElement = todoItemElement.querySelector(".delete");
              deleteButtonElement.addEventListener("click", () => {
                  this.#todoListModel.deleteTodo({
                      id: item.id
                  });
              });
              todoListElement.appendChild(todoItemElement);
          });
  • TodoListModel.js
    filterでidが一致するものを取り除く
    /**
     * 指定したidのTodoItemを削除する
     * @param {{ id: number }}
     */
    deleteTodo({ id }) {
        // `id`に一致しないTodoItemだけを残すことで、`id`に一致するTodoItemを削除する
        this.#items = this.#items.filter(todo => {
            return todo.id !== id;
        });
        this.emitChange();
    }

次回の修正点

  • リファクタリング

Discussion