纯JavaScript实现Todo列表:点击DONE按钮仅首个项变绿问题求助
问题原因
你遇到的问题核心是所有列表项都使用了重复的id="item"——HTML规范中id必须是唯一标识,document.getElementById('item')只会返回页面中第一个匹配该id的元素,因此只有第一个列表项能响应变色操作。
解决方案
方案1:修改现有逻辑,传递元素引用
直接调整addItem和change函数,让按钮点击时传递对应的列表项元素,摆脱对重复id的依赖:
const list = [] function addItem() { // 声明局部变量,避免全局污染 const task = document.getElementById('add').value; if (!task) return; // 跳过空任务 list.push(task); // 移除重复id,改用class标识列表项,同时让按钮点击时传递父元素li document.getElementById('unList').innerHTML += "<li class='todo-item'>" + task + "<button onclick='change(this.parentElement)'>done</button></li>"; // 清空输入框提升体验 document.getElementById('add').value = ''; } function change(item) { item.style.backgroundColor = 'green'; }
方案2:事件委托(推荐)
使用事件委托机制,仅给父元素<ul>绑定一次事件监听,通过事件冒泡处理所有按钮点击,更符合现代JavaScript开发规范,且性能更优:
第一步:修改addItem生成的列表项代码
移除按钮的onclick属性,改用class标识按钮:
const list = []; const unList = document.getElementById('unList'); function addItem() { const task = document.getElementById('add').value; if (!task) return; list.push(task); unList.innerHTML += "<li class='todo-item'>" + task + "<button class='done-btn'>done</button></li>"; document.getElementById('add').value = ''; }
第二步:添加事件委托监听
// 给ul绑定点击事件,利用事件冒泡处理所有子按钮的点击 unList.addEventListener('click', function(e) { // 判断点击的元素是done按钮 if (e.target.classList.contains('done-btn')) { // 找到对应的列表项li const todoItem = e.target.closest('.todo-item'); todoItem.style.backgroundColor = 'green'; } });
补充说明
- 事件委托的优势:无需为每个动态添加的按钮单独绑定事件,后续新增的列表项按钮也能自动生效;减少事件绑定数量,提升页面性能。
- 始终使用
const/let声明变量,避免未声明的变量成为全局变量造成污染。
内容的提问来源于stack exchange,提问作者bmurph510
相关产品推荐
相关产品推荐

