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

静态Todo应用触发隐藏已完成复选框后删除与完成功能失效

问题原因

  1. 你的删除、标记完成事件仅在页面首次加载时绑定了一次,触发「隐藏已完成」功能后会调用render函数清空原有DOM并生成新的任务元素,新生成的元素没有绑定对应的交互事件,因此功能失效。搜索功能触发后也会出现相同问题。
  2. 存在隐藏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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 06:27:03