🤖
JavaScript PrimerのTodoアプリ作成でJS復習(アイテムの更新、削除)
記事概要
JSの復習として、JavaScript PrimerのTodoアプリ作成をやってみて、結構いい復習になったので紹介
この続き
対象読者
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