求助: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
相关产品推荐
相关产品推荐

