静态Todo应用触发隐藏已完成复选框后删除与完成功能失效
问题原因
- 你的删除、标记完成事件仅在页面首次加载时绑定了一次,触发「隐藏已完成」功能后会调用
render函数清空原有DOM并生成新的任务元素,新生成的元素没有绑定对应的交互事件,因此功能失效。搜索功能触发后也会出现相同问题。 - 存在隐藏bug:筛选(隐藏已完成、搜索)后渲染的列表索引和localStorage中存储的完整待办数组索引不匹配,直接用当前列表的索引操作会出现删错任务、修改错任务状态的问题。
修复方案
改动1:给每个待办项增加唯一标识,避免索引匹配错误
修改addTask函数,给新增的待办项加唯一ID:
//function for adding a new task let addTask = function(todo){ let td = document.getElementById("new-task").value; let status = false; // 增加id字段,用时间戳保证唯一 let node = {td : td,status : status, id: Date.now()}; todo.push(node); saveTask(todo); // saving it to local storage newTask(node); }
修改newTask函数,给每个任务容器挂载ID属性:
let newTask = function(node) { let li = document.createElement("li"); let status = document.createElement("input"); let remove = document.createElement("button"); li.textContent = node.td; remove.setAttribute("class","remove"); remove.textContent="Delete"; status.setAttribute("type","checkbox"); status.setAttribute("class","status"); status.checked = node.status; li.style.textDecoration = (node.status)?"line-through":"none"; let div = document.createElement("div"); div.setAttribute("class","task"); // 把唯一ID存在自定义属性里 div.setAttribute("data-id",node.id); div.appendChild(status); div.appendChild(li); div.appendChild(remove); document.querySelector("#td").appendChild(div); document.getElementById("new-task").value = ""; //clearing the input feild }
改动2:封装事件绑定函数,每次渲染后重新绑定
删除main.js中原有的绑定删除、标记完成事件的代码,新增bindEvents函数,并在render调用后执行:
// 放在todoFunctions.js的render函数里修改 let render = function(list){ document.querySelector("#td").innerHTML = ""; list.forEach(function(item){ newTask(item); }) // 渲染完成后立刻绑定事件 bindEvents(); }
// 放在main.js里 function bindEvents() { // 绑定删除事件 document.querySelectorAll(".remove").forEach(function(item){ item.addEventListener("click",function(e){ // 从自定义属性拿ID匹配原始数组的真实索引 const taskId = Number(e.target.parentElement.dataset.id); const realIndex = todo.findIndex(item => item.id === taskId); deleteTodo(e,realIndex,todo); // 如果开启了隐藏已完成,操作后重新渲染 if(document.querySelector('#hide-check').checked) { hideCompleted({target: document.querySelector('#hide-check')}, todo); } }) }) // 绑定状态修改事件 document.querySelectorAll(".status").forEach(function(item){ item.addEventListener("change",function(e){ const taskId = Number(e.target.parentElement.dataset.id); const realIndex = todo.findIndex(item => item.id === taskId); changeStatus(e,realIndex,todo); // 如果开启了隐藏已完成,操作后重新渲染 if(document.querySelector('#hide-check').checked) { hideCompleted({target: document.querySelector('#hide-check')}, todo); } }) }) }
改完之后所有场景下的删除、标记完成功能都可以正常运行,也不会出现索引匹配错误的问题。
内容的提问来源于stack exchange,提问作者Abhishek Tomar
相关产品推荐
相关产品推荐

