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

JavaScript问题:如何让动态生成的每个文本框对应按钮独立生效?

问题根源

你的核心问题是每次操作都用document.querySelector()获取元素,这个方法只会返回匹配到的第一个元素,所以不管点击哪个按钮,都会操作第一个生成的文本框。解决思路是利用DOM元素的层级关系,从点击的按钮出发,找到它所属的任务项(li),再在这个范围内查找对应的文本框,这样就能实现按钮和文本框的一一对应。

具体修正步骤

1. 处理「待办列表」的编辑按钮

在deletecheckbox函数中,当点击.edit_btn时,不要用全局的document.querySelector(".newbox"),而是通过点击的按钮找到它所在的li.todo-item,再在这个li里找.newbox:

if (item.classList.contains('edit_btn')) {
  // 找到当前按钮所属的li
  const todoItem = item.closest('.todo-item');
  // 在这个li里找对应的输入框
  const textinput = todoItem.querySelector('.newbox');
  // 切换disabled状态
  textinput.disabled = !textinput.disabled;
}

同时删除之前错误的editButton = document.querySelector(".edit_btn"); editButton.addEventListener('click', change());代码——事件委托已经通过ullist.addEventListener('click', deletecheckbox)处理,不需要单独绑定。

2. 处理「完成任务」按钮

点击.complete_btn时,获取当前任务项的文本值,要从当前li里找.newbox:

if (item.classList.contains('complete_btn')) {
  const radera1 = item.parentElement;
  // 找到当前li里的输入框,获取值
  const currentInput = radera1.querySelector('.newbox');
  const taskValue = currentInput.value;

  // 生成已完成任务的代码...
  // 给新生成的输入框赋值
  textinput2.value = taskValue;

  radera1.remove();
}

3. 处理「已完成列表」的编辑按钮

在donebox函数中,同样通过点击的按钮找到所属的li.todo-item2,再找对应的.newbox2:

if (item1.classList.contains('edit_btn1')) {
  const doneItem = item1.closest('.todo-item2');
  const textinput2 = doneItem.querySelector('.newbox2');
  textinput2.disabled = !textinput2.disabled;
}
完整修正后的JavaScript代码
const syssla = document.querySelector("#min-syssla");
const firstbutton = document.querySelector(".firstbutton");
const ullist = document.querySelector(".unorderedlist");
const listdone = document.querySelector(".list-done");

firstbutton.addEventListener("click", task);

function task(event) {
  const tododiv = document.createElement("div");
  tododiv.classList.add("todo");

  const list = document.createElement('li');
  list.classList.add('todo-item');
  tododiv.appendChild(list);

  const completedButton = document.createElement('button');
  completedButton.innerText = "Färdig";
  completedButton.classList.add("complete_btn");
  list.appendChild(completedButton);

  const editButton = document.createElement('button');
  editButton.innerText = "Ändra";
  editButton.classList.add("edit_btn");
  list.appendChild(editButton);

  const eraseButton = document.createElement('button');
  eraseButton.innerText = "Radera";
  eraseButton.classList.add("erase_btn");
  list.appendChild(eraseButton);

  const textinput = document.createElement("input");
  textinput.type = "text";
  textinput.disabled = true; // 直接设置disabled属性更简洁
  textinput.classList.add("newbox");
  list.appendChild(textinput);
  textinput.value = syssla.value;

  ullist.appendChild(tododiv);

  // 清空输入框,修正之前的逻辑错误
  syssla.value = "";

  event.preventDefault();
}

ullist.addEventListener('click', deletecheckbox);

function deletecheckbox(e) {
  const item = e.target;
  
  // 删除待办任务
  if (item.classList.contains('erase_btn')) {
    const make = item.parentElement;
    make.remove();
  }

  // 完成任务
  if (item.classList.contains('complete_btn')) {
    const radera1 = item.parentElement;
    const currentInput = radera1.querySelector('.newbox');
    const taskValue = currentInput.value;

    const tododiv2 = document.createElement("div");
    tododiv2.classList.add("todo2");

    const list2 = document.createElement('li');
    list2.classList.add('todo-item2');
    tododiv2.appendChild(list2);

    const editButton1 = document.createElement('button');
    editButton1.innerText = "Ändra";
    editButton1.classList.add("edit_btn1");
    list2.appendChild(editButton1);

    const eraseButton1 = document.createElement('button');
    eraseButton1.innerText = "Radera";
    eraseButton1.classList.add("erase_btn1");
    list2.appendChild(eraseButton1);

    const textinput2 = document.createElement("input");
    textinput2.type = "text";
    textinput2.disabled = true;
    textinput2.classList.add("newbox2");
    list2.appendChild(textinput2);
    textinput2.value = taskValue;

    listdone.appendChild(tododiv2);
    radera1.remove();
  }

  // 编辑待办任务
  if (item.classList.contains('edit_btn')) {
    const todoItem = item.closest('.todo-item');
    const textinput = todoItem.querySelector('.newbox');
    textinput.disabled = !textinput.disabled;
  }
}

listdone.addEventListener('click', donebox);

function donebox(ev) {
  const item1 = ev.target;
  
  // 删除已完成任务
  if (item1.classList.contains('erase_btn1')) {
    const eraser = item1.parentElement;
    eraser.remove();
  }

  // 编辑已完成任务
  if (item1.classList.contains('edit_btn1')) {
    const doneItem = item1.closest('.todo-item2');
    const textinput2 = doneItem.querySelector('.newbox2');
    textinput2.disabled = !textinput2.disabled;
  }
}
额外优化点
  • 用element.disabled = true/false代替setAttribute/removeAttribute,更符合DOM属性操作规范。
  • 修正了清空输入框的逻辑错误:应该清空syssla.value而非firstbutton.value。
  • 用classList.contains()代替classList[0] === 'xxx',避免类名顺序变化导致判断失败,逻辑更健壮。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 08:35:19