如何实现待办列表<li>项删除功能并修复删除错位问题(含localStorage)
待办列表删除功能修复方案
问题描述
开发HTML/CSS/JavaScript待办列表时,点击第二个任务的删除按钮总是删除第一个任务。需要通过[data-text]属性区分任务项,实现点击删除按钮即可删除对应任务,并同步更新localStorage中的数据。
核心问题分析
- 删除按钮的点击事件未关联对应任务,无法识别当前操作的是哪个任务项
deleteTask函数错误处理DOM元素集合,未正确定位到被点击按钮所属的任务项- 未完成任务数组与localStorage的同步更新
修复步骤
1. 优化删除按钮的生成逻辑
移除内联onclick属性,改用事件委托处理点击事件,避免绑定冗余逻辑:
// 原删除按钮模板修改为 let collapseBtn = `<button id="clsBtn" type="button" class="close" data-dismiss="alert" aria-label="Close"> <span aria-hidden="true">×</span> </button>`;
2. 重写deleteTask函数
根据任务文本定位DOM元素,同步更新DOM、任务数组和localStorage:
function deleteTask(taskText) { // 定位对应任务项 const targetLi = document.querySelector(`[data-text="${taskText}"]`); if (targetLi) { // 从DOM移除任务项 targetLi.remove(); // 从任务数组中过滤掉当前任务 taskList = taskList.filter(task => task !== taskText); // 更新localStorage localStorage.setItem('tasks', JSON.stringify(taskList)); // 弹出删除成功提示 toastBody.innerHTML = `<p class="text-success">Görev silindi.</p>`; toastImg.innerHTML = `<img id="toastImg" style="width: 15px;" src="img/trash-solid.svg" class="rounded mr-2" alt="">`; $('#liveToast').toast('show'); } }
3. 用事件委托绑定删除事件
给任务列表容器添加点击事件监听,通过事件冒泡找到删除按钮,获取对应任务文本后调用删除函数:
ulEl.addEventListener('click', function(e) { const closeBtn = e.target.closest('.close'); if (closeBtn) { const targetLi = closeBtn.closest('.list-group-item'); const taskText = targetLi.getAttribute('data-text'); deleteTask(taskText); } });
4. 修复localStorage存储方式
改用JSON格式存储任务数组,避免任务文本含逗号导致的拆分错误:
// 初始化任务数组 let taskList = !localStorage.getItem('tasks') ? [] : JSON.parse(localStorage.getItem('tasks')); // 更新localStorage时 localStorage.setItem('tasks', JSON.stringify(taskList));
完整修复后的JavaScript代码
var TASK = document.querySelector('#task'); let ulEl = document.querySelector('#list'); const toastEl = document.querySelector('#liveToast'); const toastBody = document.querySelector('.toast-body'); const toastImg = document.querySelector('#toast-img'); // 用JSON格式初始化任务数组 let taskList = !localStorage.getItem('tasks') ? [] : JSON.parse(localStorage.getItem('tasks')); // 删除按钮模板(无内联事件) let collapseBtn = `<button id="clsBtn" type="button" class="close" data-dismiss="alert" aria-label="Close"> <span aria-hidden="true">×</span> </button>`; // 加载localStorage中的任务 if(taskList.length>0){ for (let i=0; i < taskList.length; i++) { const liDOM = document.createElement('li'); liDOM.innerHTML = `${taskList[i]} ${collapseBtn}`; liDOM.classList.add('list-group-item','d-flex', 'justify-content-between', 'align-items-center'); liDOM.setAttribute('data-text', taskList[i]); ulEl.append(liDOM); } } // 检查任务是否已存在 function checkForText(text) { return taskList.some(task => task.toLowerCase() === text.toLowerCase()); } // 添加新任务 function newElement (){ const taskValue = TASK.value.trim(); if (taskValue.length > 0){ if(checkForText(taskValue)){ toastBody.innerHTML = `<p class= "text-danger"> Eklemek istediğiniz görev listede mevcut!!</p>` toastImg.innerHTML = `<img id="toastImg" style="width: 5px;" src="img/exclamation-solid.svg" class="rounded mr-2" alt="">` $('#liveToast').toast('show'); }else{ const liDOM = document.createElement('li'); liDOM.innerHTML = `${taskValue} ${collapseBtn}`; liDOM.classList.add('list-group-item','d-flex', 'justify-content-between', 'align-items-center'); liDOM.setAttribute('data-text', taskValue); ulEl.append(liDOM); taskList.push(taskValue); localStorage.setItem('tasks', JSON.stringify(taskList)); toastBody.innerHTML = `<p class= "text-success">Görev listeye eklendi.</p>`; toastImg.innerHTML = `<img id="toastImg" style="width: 15px;" src="img/check-solid.svg" class="rounded mr-2" alt="">` $('#liveToast').toast('show'); } }else{ toastBody.innerHTML = `<p class= "text-danger">Listeye boş ekleme yapamazsınız!!</p>` toastImg.innerHTML = `<img id="toastImg" style="width: 5px;" src="img/exclamation-solid.svg" class="rounded mr-2" alt="">` $('#liveToast').toast('show'); } TASK.value= ''; } // 删除任务函数 function deleteTask(taskText) { const targetLi = document.querySelector(`[data-text="${taskText}"]`); if (targetLi) { targetLi.remove(); taskList = taskList.filter(task => task !== taskText); localStorage.setItem('tasks', JSON.stringify(taskList)); toastBody.innerHTML = `<p class="text-success">Görev silindi.</p>`; toastImg.innerHTML = `<img id="toastImg" style="width: 15px;" src="img/trash-solid.svg" class="rounded mr-2" alt="">`; $('#liveToast').toast('show'); } } // 事件委托处理删除点击 ulEl.addEventListener('click', function(e) { const closeBtn = e.target.closest('.close'); if (closeBtn) { const targetLi = closeBtn.closest('.list-group-item'); const taskText = targetLi.getAttribute('data-text'); deleteTask(taskText); } });
说明
- 采用事件委托绑定删除事件,避免内联代码,提升代码可维护性
- 改用JSON格式存储任务数组,解决任务文本含特殊字符导致的数据错误
- 删除操作同步更新DOM、任务数组和localStorage,确保数据一致性
内容的提问来源于stack exchange,提问作者Frontnost
相关产品推荐
相关产品推荐

