为何使用该JavaScript代码无法正常删除待办列表项?
问题分析
当前代码的核心问题在于:
- 用HTML字符串数组存储待办项,删除时依赖按钮的class名过滤,耦合度极高,且
keyGen持续递增,导致删除后重新渲染的按钮class与数组中存储的字符串不匹配 - 每次删除后重新绑定事件时,通过
document.querySelector(.deleteButton${i+1})查找按钮,但该选择器是基于数组长度生成的,而非实际存在的按钮class,会出现找不到按钮的情况,最终抛出Cannot read properties of null (reading 'addEventListener')错误,导致所有删除按钮失效
修复方案
改用对象数组存储待办项,结合事件委托处理删除逻辑,彻底避免事件绑定混乱的问题:
修复后的JavaScript代码
'use strict' const addButton = document.querySelector('#addButton'); const inputArea = document.querySelector('#content'); const listContainer = document.querySelector('#listContainer'); let todoId = 1; let arrayOfTodoList = []; // 添加待办项 addButton.addEventListener('click', () => { const content = inputArea.value.trim(); if (!content) return; // 空内容不添加 arrayOfTodoList.push({ id: todoId++, content }); renderTodoList(); inputArea.value = ''; }) // 渲染整个待办列表 function renderTodoList() { listContainer.innerHTML = arrayOfTodoList.map(todo => ` <li data-id="${todo.id}"> ${todo.content} <button class="deleteButton">Delete</button> </li> `).join(''); } // 事件委托处理删除:监听父容器,统一处理子按钮的点击 listContainer.addEventListener('click', (e) => { if (e.target.classList.contains('deleteButton')) { const todoId = parseInt(e.target.closest('li').dataset.id); arrayOfTodoList = arrayOfTodoList.filter(todo => todo.id !== todoId); renderTodoList(); } })
对应的HTML代码(无需修改)
<div class="controls"> <h1>Welcome to <span>TODO</span></h1> <input type="text" id="content" /> <button id="addButton">Add</button> </div> <div id="containerTodo"> <ul id="listContainer"> </ul> </div>
关键修改说明
- 数据结构优化:将HTML字符串数组改为存储包含
id和content的对象数组,数据与视图彻底解耦,删除时通过唯一id精准定位待办项 - 事件委托替代重复绑定:直接在父容器
listContainer上绑定一次点击事件,通过判断点击目标是否为删除按钮来处理逻辑,无需每次渲染后重新绑定事件,避免了事件绑定混乱和空指针错误 - 空内容过滤:添加待办项时先过滤空输入,提升用户体验
- 简化渲染逻辑:用
map方法直接生成所有待办项的HTML,代码更简洁易维护
内容的提问来源于stack exchange,提问作者Tashif Iqbal
相关产品推荐
相关产品推荐

