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

JavaScript待办列表问题:删除全部项时最后一项残留页面求助

待办列表删除最后一项残留问题修复

问题描述

向待办列表添加多个项后,删除所有项时最后一项始终留在页面上。用Splice()删除对应项后,控制台打印的todoList数组显示已清空,但页面上最后一项没被移除。

原代码

JavaScript

const todoList = [];
const newItemAdd = document.getElementById("newItemAdd");
const reset = document.getElementById("reset");

newItemAdd.onclick = addItem;
newItemTitle.onkeydown = function press() {
  if (event.key === "Enter") {
    addItem();
  }
};

function addItem() {
  let todoListRender = "";
  if (newItemTitle.value !== "") {
    todoList.push(newItemTitle.value);
  }
  for (let i = 0; i < todoList.length; i++) {
    const todo = todoList[i];
    let html = `
      <p>
        ${todo}
        <button onclick="
          todoList.splice(${i}, 1);
          addItem();
          console.log(todoList);
        ">Delete</button>
      </p>
      `;
    todoListRender += html;
    document.querySelector("#todoDiv").innerHTML = todoListRender;
    newItemTitle.value = "";
  }
}

reset.onclick = function () {
  todoList.length = 0;
  newItemTitle.value = "";
  document.querySelector("#todoDiv").innerText = "";
  addItem();
};

HTML

<p id='title'>Todo List</p>
<input id='newItemTitle' placeholder='Todo name'>
<input type='date' id='newItemDate'>
<button id='newItemAdd'>Add</button>
<button id='reset' class='test'>Reset</button>
<div id='todoDiv'></div>

问题根源

  1. 渲染逻辑漏洞:addItem函数中,每次循环迭代都更新DOM,但当todoList为空时,循环直接跳过,导致DOM不会被清空,最后一项残留。
  2. 内联索引失效:删除按钮的内联onclick硬编码了渲染时的索引${i},数组元素删除后后续元素索引变化,会导致删除位置错误。
  3. 重置操作冗余:重置时手动清空innerText后又调用addItem,但addItem在数组为空时不会更新DOM,反而可能引发冲突。

修复方案

拆分渲染逻辑,使用事件委托处理删除,确保DOM状态始终和数组一致:

修复后的JavaScript

const todoList = [];
const newItemAdd = document.getElementById("newItemAdd");
const reset = document.getElementById("reset");
const todoDiv = document.querySelector("#todoDiv");
const newItemTitle = document.getElementById("newItemTitle");

// 绑定添加事件
newItemAdd.onclick = addItem;
newItemTitle.onkeydown = function press(event) {
  if (event.key === "Enter") {
    addItem();
  }
};

// 添加待办项
function addItem() {
  const inputValue = newItemTitle.value.trim();
  if (inputValue) {
    todoList.push(inputValue);
    newItemTitle.value = "";
  }
  renderTodoList();
}

// 专门负责渲染待办列表
function renderTodoList() {
  let todoHtml = "";
  todoList.forEach((todo, index) => {
    todoHtml += `
      <p>
        ${todo}
        <button class="delete-btn" data-index="${index}">Delete</button>
      </p>
    `;
  });
  todoDiv.innerHTML = todoHtml;
}

// 事件委托处理删除按钮点击
todoDiv.addEventListener("click", (event) => {
  if (event.target.classList.contains("delete-btn")) {
    const index = parseInt(event.target.dataset.index);
    todoList.splice(index, 1);
    renderTodoList();
    console.log(todoList);
  }
});

// 重置功能
reset.onclick = function () {
  todoList.length = 0;
  newItemTitle.value = "";
  renderTodoList();
};

修复说明

  • 拆分渲染职责:单独写renderTodoList函数负责DOM渲染,添加、删除、重置操作后统一调用它,确保DOM和数组状态同步。
  • 事件委托删除:通过父元素todoDiv监听点击,动态获取当前项的索引进行删除,避免内联onclick的索引失效问题。
  • 空数组处理:当todoList为空时,renderTodoList生成空字符串,直接清空todoDiv内容,解决最后一项残留问题。
  • 输入优化:添加trim()过滤输入空格,避免添加空待办项。
  • 修复事件参数:keydown事件传入event参数,避免严格模式下报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 12:25:15