iT邦幫忙

2025 iThome 鐵人賽

DAY 24
0
佛心分享-IT 人自學之術

30 天體驗:從程式菜鳥到前端新手工程師系列 第 24

讓清單「更聰明」— 加入 Enter 快捷鍵 + localStorage 資料儲存 (Day24)

  • 分享至 

  • xImage
  •  

昨天我們做出了會動的待辦清單 ✅
但如果你一關掉網頁,清單就不見了對吧?

今天,我們要讓它變成「會記得你的任務」的版本!
我們會新增兩個進階功能:

1️⃣ 按下 Enter 也能新增任務
2️⃣ 使用 localStorage 把任務存在瀏覽器裡

🎯 今日目標
• 了解什麼是 localStorage
• 實作資料儲存、讀取功能
• 增加 Enter 鍵快捷操作

🧩 Step 1:讓 Enter 也能新增任務

我們昨天只能點「新增」按鈕。
現在要讓使用者在輸入框按下 Enter 鍵 也能新增任務。

在 script.js 裡加上這段

taskInput.addEventListener('keypress', (e) => {
  if (e.key === 'Enter') {
    addTask();
  }
});

但是這樣會重複寫太多邏輯,所以我們可以把「新增任務」包成一個函式:

function addTask() {
  const taskText = taskInput.value.trim();
  if (taskText === '') {
    alert('請輸入任務內容!');
    return;
  }

  const li = document.createElement('li');
  li.innerHTML = `
    <span>${taskText}</span>
    <button class="deleteBtn">刪除</button>
  `;
  taskList.appendChild(li);
  taskInput.value = '';

  saveTasks(); // 每次新增都儲存
}

addBtn.addEventListener('click', addTask);
taskInput.addEventListener('keypress', (e) => {
  if (e.key === 'Enter') addTask();
});

這樣不論你是按「新增」或按下 Enter 鍵,
都會觸發同一個功能,程式碼更乾淨好維護

💾 Step 2:什麼是 localStorage?

localStorage 是瀏覽器內建的儲存空間。
它能讓你的資料「存在電腦裡」,
就算你關掉網頁、重開電腦,資料也還在。

想像成「小型資料庫」,專門記錄使用者的設定或清單資料。

• 使用 localStorage.setItem(key, value) 可以存資料
• 使用 localStorage.getItem(key) 可以取資料
• 使用 localStorage.removeItem(key) 可以刪除

⚠️ 注意:它只能儲存「字串」,
所以如果要存清單(陣列),要用 JSON.stringify() 轉成字串來存。

🧱 Step 3:把清單資料存起來

我們要在每次「新增、刪除、完成任務」後,都自動更新儲存內容。

新增一個 saveTasks() 函式:

function saveTasks() {
  const tasks = [];
  document.querySelectorAll('#taskList li').forEach(li => {
    const text = li.querySelector('span').innerText;
    const completed = li.classList.contains('completed');
    tasks.push({ text, completed });
  });

  localStorage.setItem('tasks', JSON.stringify(tasks));
}

說明:
• 先把所有 < li > 拿出來,
• 取出每個任務的文字和完成狀態,
• 存成一個物件 {text, completed},
• 最後整個清單用 JSON.stringify() 存進 localStorage。

🔄 Step 4:重新開網頁時載入資料

接著,我們要在開啟頁面時,把之前存的任務重新顯示出來!

function loadTasks() {
  const saved = localStorage.getItem('tasks');
  if (saved) {
    const tasks = JSON.parse(saved);
    tasks.forEach(t => {
      const li = document.createElement('li');
      li.innerHTML = `
        <span>${t.text}</span>
        <button class="deleteBtn">刪除</button>
      `;
      if (t.completed) li.classList.add('completed');
      taskList.appendChild(li);
    });
  }
}

loadTasks(); // 一開始載入時執行

🧹 Step 5:在刪除和標記完成時也更新儲存

讓清單保持最新資料:

taskList.addEventListener('click', (e) => {
  if (e.target.tagName === 'SPAN') {
    e.target.parentElement.classList.toggle('completed');
    saveTasks();
  } else if (e.target.classList.contains('deleteBtn')) {
    e.target.parentElement.remove();
    saveTasks();
  }
});

✅ 最終整合範例

HTML

<div class="todo-container">
  <h2>📋 我的待辦清單</h2>
  <div class="input-area">
    <input type="text" id="taskInput" placeholder="請輸入任務..." />
    <button id="addBtn">新增</button>
  </div>
  <ul id="taskList"></ul>
</div>

JS

  const addBtn = document.getElementById('addBtn');
  const taskInput = document.getElementById('taskInput');
  const taskList = document.getElementById('taskList');

  function addTask() {
    const taskText = taskInput.value.trim();
    if (taskText === '') {
      alert('請輸入任務內容!');
      return;
    }

    const li = document.createElement('li');
    li.innerHTML = `
      <span>${taskText}</span>
      <button class="deleteBtn">刪除</button>
    `;
    taskList.appendChild(li);
    taskInput.value = '';
    saveTasks();
  }

  function saveTasks() {
    const tasks = [];
    document.querySelectorAll('#taskList li').forEach(li => {
      const text = li.querySelector('span').innerText;
      const completed = li.classList.contains('completed');
      tasks.push({ text, completed });
    });
    localStorage.setItem('tasks', JSON.stringify(tasks));
  }

  function loadTasks() {
    const saved = localStorage.getItem('tasks');
    if (saved) {
      const tasks = JSON.parse(saved);
      tasks.forEach(t => {
        const li = document.createElement('li');
        li.innerHTML = `
          <span>${t.text}</span>
          <button class="deleteBtn">刪除</button>
        `;
        if (t.completed) li.classList.add('completed');
        taskList.appendChild(li);
      });
    }
  }

  addBtn.addEventListener('click', addTask);
  taskInput.addEventListener('keypress', (e) => {
    if (e.key === 'Enter') addTask();
  });

  taskList.addEventListener('click', (e) => {
    if (e.target.tagName === 'SPAN') {
      e.target.parentElement.classList.toggle('completed');
      saveTasks();
    } else if (e.target.classList.contains('deleteBtn')) {
      e.target.parentElement.remove();
      saveTasks();
    }
  });

  loadTasks();

🌟 今日總結

今天我們讓待辦清單變得更聰明了 🧠:

✅ 新增任務(按鈕 & Enter)
✅ 標記完成
✅ 刪除任務
✅ 自動儲存與讀取資料

這樣你的 To-Do List 就能永久記住你的任務,
即使你重新整理頁面也不會消失啦 🎉

🔮 明日預告

明天(Day 25)我們要讓整個清單更「完整」:
• 新增任務分類(進行中 / 已完成)
• 一鍵清空所有任務 🧹

距離完成我們的清單小網站越來越有雛型了!
希望大家都有收穫滿滿~
我是Ting,謝謝你的收看
明天繼續一起完成我們的清單小專案吧~


上一篇
進化你的網頁-讓清單真的「動起來」!(Day23)
下一篇
清單再進化 — 加入分類切換 + 一鍵清空功能 (Day25)
系列文
30 天體驗:從程式菜鳥到前端新手工程師30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言