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

JavaScript待办列表编辑异常:总是更新首个列表项而非目标项

解决Todo-list编辑时总是修改第一个项的问题

问题根源

你代码里的核心问题是每次点击Edit按钮时,都给add按钮绑定了新的click事件,这些事件会叠加累积。比如你添加3个任务,每个任务的Edit按钮被点击时,都会给add按钮加一次点击事件,当你点击Save时,这3个事件会依次执行,而最早的那个事件对应的是第一个任务的元素,所以最后看起来总是修改第一个项。

修复方案

换个思路:用一个变量记录当前正在编辑的任务元素,然后在表单提交时统一处理「添加新任务」和「保存编辑任务」两种逻辑,避免重复绑定事件。

修改后的完整代码

HTML(无需修改)

<header id="header">
  <h1>Todo-list</h1>
  <form id="form">
    <input type="text" id="text" required>
    <input type="submit" class="add-task" value="add-task">
  </form>

</header>
<section>
  <div class="tasks">
    <h2>Tasks</h2>
    <!--<div class="task">
            <div class="content">
                <input type="text" class="task-added" readonly>
            </div>
            <div class="actions">
                <input type="button" class="edit" value="Edit">
                <input type="button" class="delete" value="Delete">
            </div>
         </div>
         !-->
  </div>
</section>

CSS(无需修改)

* {
  box-sizing: border-box;
}

body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  background-color: rgba(255, 255, 255, 0.918);
}

header {
  display: flex;
  flex-direction: column;
  gap: 20px;
  justify-content: center;
  align-items: center;
}

#form {
  display: flex;
  gap: 5px;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}

header h1 {
  color: orangered;
}

#form #text {
  padding: 10px;
  border-radius: 10px;
  background-color: orange;
  color: black;
  border: none;
  outline: none;
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
  -ms-border-radius: 10px;
  -o-border-radius: 10px;
}

#form .add-task {
  padding: 10px;
  border: none;
  outline: none;
  border-radius: 10px;
  color: black;
  background-color: orangered;
  cursor: pointer;
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
  -ms-border-radius: 10px;
  -o-border-radius: 10px;
}

.tasks {
  display: flex;
  gap: 5px;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.task {
  padding: 20px;
  display: flex;
  background-color: orangered;
  gap: 10px;
  border-radius: 5px;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  -ms-border-radius: 5px;
  -o-border-radius: 5px;
}

.task .content .task-added {
  outline: none;
  border: none;
  color: black;
  padding: 10px;
  border-radius: 5px;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  -ms-border-radius: 5px;
  -o-border-radius: 5px;
}

.task .content .task-added:not(:read-only) {
  color: rgb(247, 2, 2);
}

.task .actions .edit {
  cursor: pointer;
  outline: none;
  background-color: black;
  border-radius: 5px;
  padding: 10px;
  border: none;
  color: orangered;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  -ms-border-radius: 5px;
  -o-border-radius: 5px;
}

.task .actions {
  display: flex;
  flex-direction: row;
  gap: 10px;
}

.task .actions .delete {
  cursor: pointer;
  background-color: black;
  outline: none;
  border-radius: 5px;
  padding: 10px;
  border: none;
  color: orangered;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  -ms-border-radius: 5px;
  -o-border-radius: 5px;
}

修改后的JavaScript

window.addEventListener('load', () => {
  const form = document.querySelector("#form");
  const input_text = document.querySelector("#text");
  const list_ele = document.querySelector(".tasks");
  const add = document.querySelector(".add-task");
  // 新增变量:记录当前正在编辑的任务输入框
  let currentEditingInput = null;

  form.addEventListener('submit', (e) => {
    e.preventDefault();
    const text = input_text.value.trim();
    if (!text) return;

    if (add.value === "Save" && currentEditingInput) {
      // 保存编辑:修改当前任务的内容
      currentEditingInput.value = text;
      // 恢复按钮状态
      add.value = "add-task";
      currentEditingInput = null;
    } else {
      // 添加新任务:和原来的逻辑一致
      let task = document.createElement("div");
      task.classList.add("task");

      let task_content = document.createElement("div");
      task_content.classList.add("content");
      task.appendChild(task_content);

      let output = document.createElement("input");
      output.classList.add("task-added")
      output.value = text;
      output.type = "text";
      output.setAttribute("readonly", "readonly");

      task_content.appendChild(output);

      let actions = document.createElement("div");
      actions.classList.add("actions");
      task.appendChild(actions);

      let edit = document.createElement("button");
      edit.classList.add("edit");
      edit.innerHTML = "Edit";
      actions.appendChild(edit);

      let DELETE = document.createElement("button");
      DELETE.classList.add("delete");
      DELETE.innerHTML = "Delete";
      actions.appendChild(DELETE);

      list_ele.appendChild(task);

      // 给Edit按钮绑定事件:只记录当前要编辑的输入框
      edit.addEventListener('click', () => {
        add.value = "Save";
        input_text.focus();
        input_text.value = output.value;
        currentEditingInput = output;
      });

      // 给Delete按钮绑定事件
      DELETE.addEventListener('click', () => {
        task.remove();
        // 如果删除的是正在编辑的任务,恢复按钮状态
        if (currentEditingInput === output) {
          add.value = "add-task";
          currentEditingInput = null;
          input_text.value = "";
        }
      });
    }
    input_text.value = "";
  });
})

关键修改点

  1. 新增currentEditingInput变量,专门记录当前正在编辑的任务输入框,避免通过DOM遍历找目标元素的混乱
  2. 把「添加任务」和「保存编辑」的逻辑统一放到表单的submit事件里,不再给add按钮重复绑定事件
  3. Edit按钮的点击事件只负责切换按钮状态、填充输入框、记录当前编辑的元素,不处理保存逻辑
  4. 新增Delete按钮的功能,同时处理删除正在编辑任务时的状态恢复

内容的提问来源于stack exchange,提问作者zebi shah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 14:06:56