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

JavaScript实现待办列表点击添加删除线功能异常求助

问题:点击待办列表项添加删除线功能异常

我是JavaScript新手,这是我第一次提问,正尝试理解事件相关知识。我想要实现的功能是:点击待办列表中的项时,为该项添加删除线以标记已完成。我尝试使用document.querySelectorAll("li")的forEach循环绑定点击事件,但没有成功,目前只有列表的第一项点击后会显示删除线。

我的JS代码

var button = document.getElementById("enter");
var input = document.getElementById("userinput");
var ul = document.querySelector("ul");
var list = document.querySelectorAll("li")

function inputLength() {
    return input.value.length;
}

function createListElement() {
    var li = document.createElement("li");
    li.appendChild(document.createTextNode(input.value));
    ul.appendChild(li);
    input.value = "";
}

function addListAfterClick() {
    if (inputLength() > 0) {
        createListElement();
    }
}

function addListAfterKeypress(event) {
    if (inputLength() > 0 && event.keyCode === 13) {
        createListElement();
    }
}

button.addEventListener("click", addListAfterClick);

input.addEventListener("keypress", addListAfterKeypress);

list.forEach(function(item) {
item.addEventListener("click", function(){
    document.querySelectorAll("li").classList.add("done");
    }); 
});

我的HTML代码

<!DOCTYPE html>
<html>
<head>
    <title>Javascript + DOM</title>
    <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
    <h1>Shopping List</h1>
    <p id="first">Get it done today</p>
    <input id="userinput" type="text" placeholder="enter items">
    <button id="enter">Enter</button>
    <ul>
        <li class="bold red" random="23">Notebook</li>
        <li>Jello</li>
        <li>Spinach</li>
        <li>Rice</li>
        <li>Birthday Cake</li>
        <li>Candles</li>
    </ul>
    <script type="text/javascript" src="script.js"></script>
</body>
</html>

我的CSS代码

.done {
  text-decoration: line-through;
}

解决方案

问题分析

  1. 核心错误:你在点击事件里调用document.querySelectorAll("li").classList.add("done"),但document.querySelectorAll("li")返回的是NodeList元素集合,集合本身没有classList属性。部分旧浏览器会把集合的属性自动映射到第一个元素,这就是只有第一项生效的原因,不属于标准行为。
  2. 遗漏新增元素绑定:仅给页面初始加载的li绑定了事件,后续通过输入添加的新li不会触发点击事件,需要补充处理。

修正后的代码

1. 修复现有li的点击逻辑

将点击事件改为针对当前被点击的元素,用this或event.target获取目标元素,同时用toggle替代add,实现点击切换已完成/未完成状态:

list.forEach(function(item) {
  item.addEventListener("click", function() {
    this.classList.toggle("done");
  }); 
});

2. 给新增li绑定点击事件

修改createListElement函数,在创建li后立即绑定点击事件:

function createListElement() {
    var li = document.createElement("li");
    li.appendChild(document.createTextNode(input.value));
    // 给新创建的li绑定点击事件
    li.addEventListener("click", function() {
      this.classList.toggle("done");
    });
    ul.appendChild(li);
    input.value = "";
}

完整修正后的JS代码

var button = document.getElementById("enter");
var input = document.getElementById("userinput");
var ul = document.querySelector("ul");
var list = document.querySelectorAll("li")

function inputLength() {
    return input.value.length;
}

function createListElement() {
    var li = document.createElement("li");
    li.appendChild(document.createTextNode(input.value));
    // 绑定点击事件到新li
    li.addEventListener("click", function() {
      this.classList.toggle("done");
    });
    ul.appendChild(li);
    input.value = "";
}

function addListAfterClick() {
    if (inputLength() > 0) {
        createListElement();
    }
}

function addListAfterKeypress(event) {
    if (inputLength() > 0 && event.keyCode === 13) {
        createListElement();
    }
}

button.addEventListener("click", addListAfterClick);

input.addEventListener("keypress", addListAfterKeypress);

// 给初始li绑定点击事件
list.forEach(function(item) {
  item.addEventListener("click", function() {
    this.classList.toggle("done");
  }); 
});

额外优化:事件委托(可选)

如果后续列表项较多,逐个绑定事件效率较低,可以使用事件委托,将事件绑定到父元素ul上,通过事件冒泡处理所有li的点击:

// 替换所有li的逐个绑定代码,仅保留这一行
ul.addEventListener("click", function(event) {
  // 确保点击的是li元素
  if (event.target.tagName === "LI") {
    event.target.classList.toggle("done");
  }
});

这种方式无需给每个li单独绑定事件,不管是初始li还是新增li,点击都会触发处理逻辑,代码更简洁高效。

内容的提问来源于stack exchange,提问作者Achilles 1996

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 10:25:27