【JS / Local Storage】To-Doリストを実装してみた

先日、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リストにリスト項目を追加
        });
    }
    1. まず、To-Doリストをクリアします。
    2. 次に、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(); // カーソルを入力フィールドに戻す
        }
    }
    1. 入力フィールドのテキストを取得し、新しいTo-Doを作成して配列todosに追加します。
      • 「取得したテキストに対して.trim()を使うと、文字列の両端にある空白を取り除くことができます。
    2. todosにはその内容textに加え、完了ステータスを判定するためのcompletedもセットします。
    3. To-Do追加後はTo-Doリストを保存saveTodos();し、To-Doリストを再表示renderTodos();します。
    4. 最後に、入力フィールドにカーソルを戻します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リストに応用し、以下ページで公開しています。
    コードも公開しているので、参考にしてみてください!

    よかったらシェアしてね!
    • URLをコピーしました!
    • URLをコピーしました!
    目次