待办列表重复添加且页面刷新后列表不保留问题求助
修复localStorage待办列表的重复渲染与刷新丢失问题
你的代码存在两个核心问题,导致任务重复显示、刷新后列表丢失:
- 页面加载完成后,没有把localStorage中存储的待办任务渲染到页面
- 每次提交表单时,遍历整个
todos数组重新渲染所有任务,导致旧任务被重复添加
以下是具体修复方案:
关键修复步骤
- 添加渲染函数:编写统一的函数负责将
todos数组内容渲染到页面,页面加载时调用一次,确保刷新后能显示历史任务 - 移除提交时的全量遍历:提交表单后只需更新数组和localStorage,再调用渲染函数即可,避免重复渲染
- 修正渲染内容:渲染任务时使用当前todo的
content字段,而非固定变量task - 完善编辑/删除逻辑:编辑时同步更新数组和localStorage,删除时通过
id精准匹配任务
修正后的完整代码
window.addEventListener('load', () => { const form = document.querySelector('#new-task-form'); const input = document.querySelector('#new-task-input'); const listElement = document.querySelector('#tasks'); // 从localStorage读取数据,没有则初始化空数组 let todos = JSON.parse(localStorage.getItem('todos')) || []; // 渲染待办列表的函数 function renderTodos() { // 先清空现有列表,避免重复 listElement.innerHTML = ''; todos.forEach(todo => { const taskElement = document.createElement('div'); taskElement.classList.add('task'); const taskContentElement = document.createElement('div'); taskContentElement.classList.add("content"); taskElement.appendChild(taskContentElement); const taskInputElement = document.createElement("input") taskInputElement.classList.add("text"); taskInputElement.type = "text"; // 使用当前todo的content,而非固定变量 taskInputElement.value = todo.content; taskInputElement.setAttribute('readonly', 'readonly'); // 给输入框绑定id,方便编辑时找到对应任务 taskInputElement.dataset.id = todo.id; taskContentElement.appendChild(taskInputElement); const taskActionsElement = document.createElement('div'); taskActionsElement.classList.add("actions"); const taskEditElement = document.createElement('button'); taskEditElement.classList.add('edit'); taskEditElement.innerHTML = "Edit"; const taskDeleteElement = document.createElement('button'); taskDeleteElement.classList.add('delete'); taskDeleteElement.innerHTML = "Delete"; taskDeleteElement.dataset.id = todo.id; taskActionsElement.appendChild(taskEditElement); taskActionsElement.appendChild(taskDeleteElement); taskElement.appendChild(taskActionsElement); listElement.appendChild(taskElement); }); // 绑定编辑和删除事件(因为每次渲染后元素是新的,所以要重新绑定) bindTaskEvents(); } // 绑定编辑和删除事件的函数 function bindTaskEvents() { // 编辑按钮事件 document.querySelectorAll('.edit').forEach(btn => { btn.addEventListener('click', (e) => { const taskInput = e.target.closest('.task').querySelector('.text'); const todoId = parseInt(taskInput.dataset.id); if (btn.innerText.toLowerCase() === 'edit') { taskInput.removeAttribute('readonly'); taskInput.focus(); btn.innerText = "Save"; } else { taskInput.setAttribute('readonly', 'readonly'); btn.innerText = 'Edit'; // 更新对应todo的内容 todos = todos.map(todo => { if (todo.id === todoId) { return {...todo, content: taskInput.value}; } return todo; }); localStorage.setItem("todos", JSON.stringify(todos)); } }); }); // 删除按钮事件 document.querySelectorAll('.delete').forEach(btn => { btn.addEventListener('click', (e) => { const taskElement = e.target.closest('.task'); const todoId = parseInt(btn.dataset.id); // 通过id过滤数组 todos = todos.filter(todo => todo.id !== todoId); localStorage.setItem('todos', JSON.stringify(todos)); listElement.removeChild(taskElement); }); }); } // 页面加载时先渲染一次列表 renderTodos(); form.addEventListener('submit', (e) => { e.preventDefault(); const task = input.value.trim(); if(!task) { alert('You definitely have something to do...') return } const todo = { content: task, // 使用时间戳生成唯一id,比随机数更可靠 id: Date.now() } todos.push(todo); localStorage.setItem('todos', JSON.stringify(todos)); // 清空输入框并重新渲染列表 input.value = ''; renderTodos(); }); });
额外优化点
- 用
Date.now()生成任务id,比随机数更不容易重复 - 给输入框和删除按钮添加
dataset.id,方便精准匹配对应任务 - 将事件绑定逻辑抽离成单独函数,避免重复代码
内容的提问来源于stack exchange,提问作者user379
相关产品推荐
相关产品推荐

