You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:ToDo List的localStorage功能实现问题

解决方案:实现带localStorage持久化的待办事项列表

你的核心问题在于没有用数组存储所有待办项,每次添加时只会覆盖单个对象,同时缺少页面加载时的渲染逻辑,以及操作(完成/删除)后的localStorage同步。下面是修改后的完整代码和关键逻辑说明:

修改后的JavaScript代码

const form = document.querySelector('#add-item');
const input = document.querySelector('#first-item');
const itemList = document.querySelector('#item-list');

// 从localStorage获取待办列表,不存在则返回空数组
function getTodos() {
  return JSON.parse(localStorage.getItem('todos')) || [];
}

// 保存待办列表到localStorage
function saveTodos(todos) {
  localStorage.setItem('todos', JSON.stringify(todos));
}

// 渲染待办列表到页面
function renderTodos() {
  itemList.innerHTML = ''; // 先清空现有列表
  const todos = getTodos();
  
  todos.forEach((todo, index) => {
    const newItem = document.createElement('li');
    const removeBtn = document.createElement('button');
    
    removeBtn.innerText = 'Remove';
    newItem.innerText = todo.name;
    // 根据状态设置样式
    if (todo.completed) {
      newItem.style.textDecoration = 'line-through';
    }
    newItem.appendChild(removeBtn);
    // 给li添加索引属性,方便后续操作
    newItem.dataset.index = index;
    itemList.appendChild(newItem);
  });
}

// 页面加载时渲染列表
document.addEventListener('DOMContentLoaded', renderTodos);

// 删除待办项
itemList.addEventListener('click', function(e) {
  if(e.target.tagName === 'BUTTON'){
    const index = e.target.parentElement.dataset.index;
    const todos = getTodos();
    todos.splice(index, 1); // 移除对应项
    saveTodos(todos);
    renderTodos(); // 重新渲染列表
  }
});

// 标记待办项完成/未完成
itemList.addEventListener('click', function(e){
  if(e.target.nodeName === 'LI'){
    const index = e.target.dataset.index;
    const todos = getTodos();
    // 切换完成状态
    todos[index].completed = !todos[index].completed;
    saveTodos(todos);
    // 更新当前项样式
    e.target.style.textDecoration = todos[index].completed ? 'line-through' : 'none';
  }
});

// 添加新待办项
form.addEventListener('submit', function(e) {
  e.preventDefault();
  const todoText = input.value.trim();
  if (!todoText) return; // 空输入不处理
  
  const todos = getTodos();
  // 添加新待办,默认未完成
  todos.push({ name: todoText, completed: false });
  saveTodos(todos);
  renderTodos(); // 重新渲染列表
  
  input.value = '';
});

修改后的HTML代码(仅修正无效的link标签)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ToDoApp</title>
    <!-- 移除无效的link标签,JS通过body末尾的script引入即可 -->
</head>
<body>
<h1>ToDo List</h1>
<form action="" id="add-item">
    <label for="first-item">First Item</label>
    <input type="text" id="first-item">
    <button>Add to List</button>
</form>
<ul id="item-list"></ul>
<script src="4.4 TODO App Exercise.js"></script>
</body>
</html>

关键逻辑说明

  • 用数组存储所有待办:不再单存一个对象,而是用数组保存所有待办项,每个项包含name(内容)和completed(完成状态)两个属性。
  • 封装读写函数:getTodos和saveTodos统一处理localStorage的读写,避免重复代码。
  • 页面加载渲染:通过DOMContentLoaded事件,页面加载时自动读取localStorage并渲染列表。
  • 操作同步存储:删除、标记完成时,先修改内存中的数组,再同步到localStorage,最后重新渲染列表(或直接更新样式)。
  • 索引标记:给每个li添加data-index属性,关联其在数组中的位置,方便快速找到对应项进行修改。

内容的提问来源于stack exchange,提问作者KupferWulf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 15:45:46