先日、JavaScriptの「Local Storage」の基本的な使い方について記事をまとめました。
今回は、より実践的な使い方として「To Do リスト(ページを更新したり閉じたりしても内容が保存される)」を実装してみたので、その手順を公開します。
To-Do リスト
- 入力フォームに To Do を入力して「Add」ボタンをクリックすると、To Do が追加される。複数追加も可能。
- 追加された To Do には完了判定用のチェックボックスがあり、チェックを入れると取り消し線が付く。
- 「Clear」ボタンをクリックするとアラートが表示され、「OK」をクリックするとTo Doがリセットされる。
- 追加 / 完了チェックしたTo DoはLocal Storageに保存されるため、リロードしたりページを閉じて再度開いたりしても作業中の内容が表示され、リセットされない。(同じPC および ブラウザからのアクセスに限る。)
HTML / CSS / JavaScript コード
<p>To-Do List</p>
<input type="text" id="new-todo" placeholder="New task...">
<button id="add-btn">Add</button>
<button id="clear-btn">Clear</button>
<ul id="todo-list"></ul>
実装のポイント
「Local Storage」に関する部分を中心に、JavaScriptのコードを解説します。
Local Storage から保存されているTo-Doリストを取得
let todos = JSON.parse(localStorage.getItem('todos')) || [];
localStorage.getItem
で保存されているTo-Doリスト(文字列)を取得し、JSON.parse
を使ってJavaScriptのオブジェクトに変換します。保存されているTo-Doリストがない場合は空の配列[]
を返します。
タスクを表示する関数 (renderTodos
)
function renderTodos() {
todoList.innerHTML = ''; // ToDoリストをクリア
todos.forEach((todo, index) => {
const li = document.createElement('li'); // ToDoのリスト項目を作成
const checkbox = document.createElement('input'); // 完了状態を示すチェックボックスを作成
checkbox.type = 'checkbox';
checkbox.checked = todo.completed; // ToDoの完了状態を設定
checkbox.addEventListener('change', () => toggleComplete(index)); // チェックボックスの状態が変わったときの処理を追加
li.appendChild(checkbox);
const span = document.createElement('span'); // ToDoの内容を表示する要素を作成
span.textContent = todo.text;
if (todo.completed) {
li.classList.add('completed'); // 完了したToDoには線を引く
}
li.appendChild(span);
todoList.appendChild(li); // ToDoリストにリスト項目を追加
});
}
- まず、To-Doリストをクリアします。
- 次に、Local Storage から取得したTo-Doリストを一つずつ取り出し、各To-Doをリスト項目の要素として作成します。各To-Doには以下2つの要素を含みます。
- 完了ステータスを判定する
checkbox
要素(チェックをいれるとテキストカラーがグレー&取り消し線が付く) - To-Doの内容を表示する
span
要素
- 完了ステータスを判定する
新しいタスクを追加する関数 (addTodo
)
// 新しいToDoを追加する関数
function addTodo() {
const text = newTodoInput.value.trim(); // 入力フィールドからテキストを取得
if (text !== '') {
todos.push({ text, completed: false }); // 新しいToDoを配列に追加
newTodoInput.value = ''; // 入力フィールドをクリア
saveTodos(); // ToDoをLocal Storageに保存
renderTodos(); // ToDoを再表示
newTodoInput.focus(); // カーソルを入力フィールドに戻す
}
}
- 入力フィールドのテキストを取得し、新しいTo-Doを作成して配列
todos
に追加します。- 「取得したテキストに対して
.trim()
を使うと、文字列の両端にある空白を取り除くことができます。
- 「取得したテキストに対して
todos
にはその内容text
に加え、完了ステータスを判定するためのcompleted
もセットします。- To-Do追加後はTo-Doリストを保存
saveTodos();
し、To-Doリストを再表示renderTodos();
します。 - 最後に、入力フィールドにカーソルを戻します
newTodoInput.focus()
。これによって次のTo-Doを作りやすくなり、ユーザビリティが向上します。
To-Doの完了状態を切り替える関数 (toggleComplete
)
// ToDoの完了状態を切り替える関数
function toggleComplete(index) {
todos[index].completed = !todos[index].completed; // ToDoの完了状態を反転
saveTodos(); // ToDoをLocal Storageに保存
renderTodos(); // ToDoを再表示
}
index
に紐づいたTo-Doの完了状態(completed
)を反転させたのち、To-Doリストを保存saveTodos();
して再表示renderTodos();
します。
全てのタスクをクリアする関数 (clearTodos
)
// 全てのToDoをクリアする関数
function clearTodos() {
if (confirm('To Do リストをすべてクリアします。よろしいですか?')) {
todos = []; // ToDoの配列を空にする
saveTodos(); // ToDoをLocal Storageに保存
renderTodos(); // ToDoを再表示
newTodoInput.focus(); // カーソルを入力フィールドに戻す
} else {
newTodoInput.focus(); // カーソルを入力フィールドに戻す
}
}
クリアボタンを押したときに確認ダイアログを表示し、ユーザーがOKを選択した場合にTo-Doをクリアtodos = [];
します。その後の処理は他と同じで、To-Doリストを保存saveTodos();
して再表示renderTodos();
し、入力フィールドにカーソルを戻します。
To-DoをLocal Storageに保存する関数 (saveTodos
)
// ToDoをLocal Storageに保存する関数
function saveTodos() {
localStorage.setItem('todos', JSON.stringify(todos)); // ToDoの配列を文字列に変換して保存
}
localStorage.setItem(key, value)
を使い、’todos’というキーでTo-Doの配列todos
をLocal Storageに保存します。
ただし、todos
は配列で各To-Doはオブジェクトとして保存されているため、JSON.stringify
を使ってJSON形式の文字列に変換します。(Local Storageに保存できるデータ型は文字列のみであるため)
【応用】タスクをドラッグ&ドロップで入れ替えられるようにする
ドラッグ&ドロップでタスクの順番を自由に入れ替えられるようにする方法について、以下記事を公開しています。
こちらを今回作成したTo Doリストに応用し、以下ページで公開しています。
コードも公開しているので、参考にしてみてください!