前回までで、動作的(機能的)にはRaiseTechのReactコースの課題の要求を概ね満たしているので、ここからは、より良いコードにするために最適化して行く。
過去記事:
今回の最適化ポイント
for の代わりに、配列のループ処理は、forEach / map / filter / reduce などのビルトインメソッドを使う。
Deleteボタン押下時の処理
JavaScript(変更前)
const deleteTasks = (deleteButton) => { const chosenTask = deleteButton.closest('li'); taskList.removeChild(chosenTask); // ローカルストレージに保存 const lStorage = getLocalStorage(); for (let i = 0; i < lStorage.length; i++) { if (lStorage[i].item === chosenTask.id) { lStorage.splice(i, 1); setLocalStorage(lStorage); break; } } };
JavaScript(変更後)
const deleteTasks = (deleteButton) => { const chosenTask = deleteButton.closest('li'); taskList.removeChild(chosenTask); // ローカルストレージに保存 setLocalStorage(getLocalStorage().filter((ls) => ls.item !== chosenTask.id)); };
Completeボタン押下時の処理
JavaScript(変更前)
const completeTasks = (completeButton) => { const chosenTask = completeButton.closest('li'); if (chosenTask.className === 'complete') { // 完了タスクを未完了に戻す chosenTask.className = 'notComplete'; completeButton.innerHTML = 'Complete'; } else { // 未完了タスクを完了にする chosenTask.className = 'complete'; completeButton.innerHTML = 'Restore'; } // 完了・未完了のデータをローカルストレージに保存 const lStorage = getLocalStorage(); for (let i = 0; i < lStorage.length; i++) { if (lStorage[i].item === chosenTask.id) { if (chosenTask.className === 'complete') { lStorage[i].comp = 1; } else { lStorage[i].comp = 0; } setLocalStorage(lStorage); break; } } };
JavaScript(変更後)
const completeTasks = (completeButton) => { const chosenTask = completeButton.closest('li'); if (chosenTask.className === 'complete') { // 完了タスクを未完了に戻す chosenTask.className = 'notComplete'; completeButton.innerHTML = 'Complete'; } else { // 未完了タスクを完了にする chosenTask.className = 'complete'; completeButton.innerHTML = 'Restore'; } // 完了・未完了のデータをローカルストレージに保存 let tempStorage = []; tempStorage = getLocalStorage().map((ls) => { if (ls.item === chosenTask.id) { ls.comp = chosenTask.className === 'complete' ? 1 : 0; } return ls; }); setLocalStorage(tempStorage); };
やること追加ボタン押下時の処理
JavaScript(変更前)
taskSubmit.addEventListener('click', (evt) => { evt.preventDefault(); const task = taskInput.value; if (task === '') { // タスク未入力は認めない window.alert('タスクを入力してください'); return; } const lStorage = getLocalStorage(); if (lStorage !== null) { for (let i = 0; i < lStorage.length; i++) { if (lStorage[i].item === task) { // タスクの重複は認めない window.alert('タスクが重複しています'); return; } } } addTasks(task); taskInput.value = ''; });
JavaScript(変更後)
taskSubmit.addEventListener('click', (evt) => { evt.preventDefault(); const task = taskInput.value; if (task === '') { // タスク未入力は認めない window.alert('タスクを入力してください'); return; } if (getLocalStorage() !== null) { if (getLocalStorage().find((ls) => ls.item === task) !== undefined) { // タスクの重複は認めない window.alert('タスクが重複しています'); return; } } addTasks(task); taskInput.value = ''; });
リロード時の処理
JavaScript(変更前)
document.addEventListener('DOMContentLoaded', () => { const lStorage = getLocalStorage(); if (lStorage === null) { taskList.textContent = ''; } else { // ローカルストレージに保存してあるデータを戻す for (let i = 0; i < lStorage.length; i++) { const listItem = document.createElement('li'); listItem.id = lStorage[i].item; if (lStorage[i].comp === 1) { listItem.setAttribute('class', 'complete'); } listItem.textContent = lStorage[i].item; taskList.appendChild(listItem); addButtons(listItem); } } });
JavaScript(変更後)
document.addEventListener('DOMContentLoaded', () => { const lStorage = getLocalStorage(); if (lStorage === null) { taskList.textContent = ''; } else { // ローカルストレージに保存してあるデータを戻す lStorage.forEach((ls) => { const listItem = document.createElement('li'); listItem.id = ls.item; if (ls.comp === 1) { listItem.setAttribute('class', 'complete'); } listItem.textContent = ls.item; taskList.appendChild(listItem); addButtons(listItem); }); } });
for でも問題ないが、mapやfind、filterを使った方が、何をしているのかがわかりやすい。(forは万能すぎて、何をしているのかを理解するのに時間がかかる。)