前回までで、動作的(機能的)には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は万能すぎて、何をしているのかを理解するのに時間がかかる。)