You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现待办列表<li>项删除功能并修复删除错位问题(含localStorage)

待办列表删除功能修复方案

问题描述

开发HTML/CSS/JavaScript待办列表时,点击第二个任务的删除按钮总是删除第一个任务。需要通过[data-text]属性区分任务项,实现点击删除按钮即可删除对应任务,并同步更新localStorage中的数据。

核心问题分析

  1. 删除按钮的点击事件未关联对应任务,无法识别当前操作的是哪个任务项
  2. deleteTask函数错误处理DOM元素集合,未正确定位到被点击按钮所属的任务项
  3. 未完成任务数组与localStorage的同步更新

修复步骤

1. 优化删除按钮的生成逻辑

移除内联onclick属性,改用事件委托处理点击事件,避免绑定冗余逻辑:

// 原删除按钮模板修改为
let collapseBtn = `<button id="clsBtn" type="button" class="close" 
data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</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">&times;</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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 05:35:42