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
相关产品推荐
相关产品推荐

