Kanban看板任务添加异常:点击列按钮无法在对应列新增任务
Kanban看板添加任务问题排查与修复
问题现象
开发简易Kanban看板时,点击每列底部的按钮,本该在对应列的ul.tasks中添加新任务,但实际点击任意按钮都只会向第一列添加任务;改用querySelectorAll选择所有ul.tasks后,又仅能向最后一列添加任务。
错误原因分析
- HTML重复ID问题:第二、第三列的按钮ID都是
btn,ID在DOM中必须唯一,这会导致后续元素选择出现不可预期的问题。 - 目标任务列表定位错误:
- 用
document.querySelector(".tasks")只会获取页面中第一个匹配的ul元素,所以所有按钮点击都往第一列添加任务。 - 若改用
querySelectorAll,如果循环绑定事件时没处理好闭包,会导致所有事件最终指向最后一个ul元素。
- 用
- 事件绑定未关联对应列:原代码中点击事件没有和按钮所在列的任务列表建立关联,始终操作同一个固定的
tasks元素。
修复方案
- 修正HTML中重复的按钮ID,保证每个ID唯一(或直接依赖class选择按钮,无需ID)。
- 在按钮点击事件中,通过父元素定位找到当前按钮所在列的
ul.tasks:利用btn.parentElement.querySelector(".tasks")获取当前row下的任务列表。 - 修改
addContent函数,让它接收目标任务列表元素作为参数,动态添加任务到对应位置。
修复后的完整代码
HTML代码
<h1>Kanban Board</h1> <div class="container"> <div class="row"> <h2>Not Started</h2> <ul class="tasks"> </ul> <button class="btn" id="btn1">+ Add(1)</button> </div> <div class="row"> <h2>In Progress</h2> <ul class="tasks"> </ul> <button class="btn" id="btn2">+ Add(2)</button> </div> <div class="row"> <h2>Completed</h2> <ul class="tasks"> </ul> <button class="btn" id="btn3">+ Add(3)</button> </div> </div>
CSS代码(无需修改)
* { margin: 0; padding: 0; box-sizing: border-box; } html { font-size: 62.5%; } body { font-family: "Roboto", sans-serif; background-color: #009578; color: #fff; display: flex; align-items: center; justify-content: center; flex-direction: column; min-height: 100vh; gap: 6rem; } h1 { font-size: 5rem; } h2 { font-size: 3.5rem; font-weight: normal; user-select: none; } .container { display: flex; align-items: center; justify-content: space-evenly; flex-wrap: wrap; gap: 5rem; width: 80%; } .row, .tasks { display: flex; flex-direction: column; gap: 1rem; } .input-container { padding: 1rem; background-color: #fff; border-radius: 4px; display: flex; align-items: center; gap: 1rem; box-shadow: 0 2px 4px rgb(0 0 0 / 20%); } .field { font-size: 1.8rem; border-radius: 0.4rem; outline: 0; border: 0; } .icon { height: 2rem; color: black; cursor: pointer; } .edit { color: #002d24; } .remove { color: red; } .btn { padding: 1rem; font-size: 1.8rem; background-color: #00866d; color: #fff; border: 0; border-radius: 4px; cursor: pointer; box-shadow: 0 2px 4px rgb(0 0 0 / 20%); } .btn:hover { background-color: #006854; }
JavaScript代码
const btns = document.querySelectorAll(".btn"); // 接收目标任务列表元素作为参数 function addContent(targetTasks) { const newElement = document.createElement("li"); newElement.className = "input-container"; const content = `<input type="text" class="field"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 edit icon"> <path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125" /> </svg> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 remove icon"> <path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" /> </svg> `; newElement.innerHTML = content; targetTasks.appendChild(newElement); } // 绑定事件时,获取当前按钮所在列的任务列表 btns.forEach((btn) => { btn.addEventListener("click", () => { // 找到当前按钮所在row下的tasks列表 const targetTasks = btn.parentElement.querySelector(".tasks"); addContent(targetTasks); }); });
额外优化点
- 移除了原代码中冗余的
input创建逻辑(因为innerHTML里已经包含了input)。 - 去掉了input的重复ID
input,避免多个任务项出现重复ID的问题。
内容的提问来源于stack exchange,提问作者Mohammed-Abol-Fotouh
相关产品推荐
相关产品推荐

