0

0

动态待办事项列表:JavaScript实现点击完成按钮切换列表项背景色

霞舞

霞舞

发布时间:2025-11-12 14:38:01

|

999人浏览过

|

来源于php中文网

原创

动态待办事项列表:JavaScript实现点击完成按钮切换列表项背景色

本教程将指导您如何使用纯javascript为动态生成的待办事项列表实现点击“完成”按钮时切换列表项背景色的功能。核心在于避免id重复问题,并通过事件处理函数传递当前元素引用 (`this`),利用dom父节点属性精准定位并修改目标列表项的样式,从而实现精确的元素操作。

在构建交互式Web应用时,动态生成内容并对其进行样式修改是常见的需求。例如,在一个待办事项列表中,我们希望用户点击“完成”按钮后,对应的待办事项能够高亮显示,以区分已完成和未完成的任务。然而,在实现这类功能时,开发者常常会遇到一个常见陷阱:使用重复的HTML id 属性来定位元素。

避免ID重复的陷阱与精准元素定位

HTML规范明确指出,id 属性在整个文档中必须是唯一的。当您使用 document.getElementById() 方法来获取元素时,它只会返回文档中第一个匹配指定ID的元素。这意味着,如果您动态生成了多个 <li> 元素,并给它们都赋予了相同的 id="item",那么 document.getElementById('item') 将永远只选中第一个 <li> 元素,导致其他列表项的样式无法被修改。

为了解决这个问题,我们需要摒弃依赖重复ID的错误做法,转而采用更精确的DOM操作技巧:

  1. 不为动态生成的元素分配重复ID。
  2. 利用事件触发时的上下文信息。 当一个按钮被点击时,该事件的上下文(即 this 关键字)会指向被点击的按钮本身。我们可以将这个 this 传递给事件处理函数。
  3. 通过DOM遍历定位目标元素。 一旦我们获得了被点击的按钮元素,就可以利用DOM的父子关系(如 parentNode)来向上追溯,找到其对应的父级 <li> 元素,进而修改其样式。

实现步骤与代码示例

下面我们将通过一个简单的待办事项列表示例,详细演示如何实现点击“完成”按钮后,切换对应列表项背景色的功能。

立即学习Java免费学习笔记(深入)”;

1. HTML 结构

首先,我们构建一个基本的HTML结构,包含一个输入框用于添加任务,一个按钮用于提交,以及一个无序列表 <ul> 来显示待办事项。

AI Web Designer
AI Web Designer

AI网页设计师,快速生成个性化的网站设计

下载
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Get Stuff Done</title>
  <link rel="stylesheet" href="todo.css" type="text/css">
</head>
<body>
  <div class="container">
    <header>
      <p>
        <h1 id="title">Todo list</h1>
        <h2 id="date"></h2>
      </p>
      <form name="myForm" method="post" action="">
        <input type="text" id="add" name="addNew">
        <button name="sumbitBtn" type="button" class="addBtn" onclick="addItem()">add</button>
        <div>
          <ul id="unList">
          </ul>
        </div>
      </form>
    </header>
  </div>

  <script type="text/javascript">
    // JavaScript 代码将在这里
  </script>
</body>
</html>

2. JavaScript 核心逻辑

我们将把JavaScript代码直接嵌入到HTML文件的 <script> 标签中,方便演示。

const list = []; // 用于存储待办事项的数组

/**
 * 添加待办事项到列表
 */
function addItem() {
  const taskInput = document.getElementById('add');
  const task = taskInput.value.trim(); // 获取输入值并去除首尾空格

  if (task === '') {
    alert('待办事项不能为空!');
    return;
  }

  list.push(task); // 将任务添加到数组

  // 获取无序列表元素
  const unList = document.getElementById('unList');

  // 动态创建列表项,并为“完成”按钮绑定事件
  // 注意:不再给<li>设置重复ID
  unList.innerHTML += `
    <li>
      ${task} 
      <button type='button' onclick='changeBackgroundColor(this)'>done</button>
    </li>`;

  taskInput.value = ''; // 清空输入框
}

/**
 * 改变列表项的背景颜色
 * @param {HTMLElement} element 被点击的“完成”按钮元素
 */
function changeBackgroundColor(element) {
  // element 参数就是被点击的按钮(因为我们在onclick中传递了this)
  // element.parentNode 获取按钮的直接父元素,即对应的 <li>
  element.parentNode.style.backgroundColor = 'green'; 
  // 也可以选择禁用按钮,表示已完成
  element.disabled = true; 
  element.textContent = 'Done!'; // 改变按钮文本
}

代码解析:

  • addItem() 函数:
    • 获取输入框的值,并进行非空校验。
    • 使用模板字符串 (`) 动态生成 <li> 元素及其内部的文本和“完成”按钮。
    • 关键在于 onclick='changeBackgroundColor(this)':当这个“完成”按钮被点击时,它会调用 changeBackgroundColor 函数,并将 this(即当前被点击的按钮元素本身)作为参数传递过去。
  • changeBackgroundColor(element) 函数:
    • 它接收一个参数 element,这个 element 就是从 onclick 事件中传递过来的被点击的按钮。
    • element.parentNode 是DOM操作中非常实用的一个属性,它返回指定元素的直接父元素。在这里,被点击的按钮的父元素就是我们想要改变背景色的 <li> 元素。
    • 通过 element.parentNode.style.backgroundColor = 'green';,我们就可以精确地将对应 <li> 元素的背景色设置为绿色。
    • 为了更好的用户体验,我们还禁用了按钮并修改了其文本。

完整示例代码

将上述HTML和JavaScript代码整合,您将得到一个功能完善的待办事项列表。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Get Stuff Done</title>
  <!-- 您可以在这里链接外部CSS文件,例如 todo.css -->
  <style>
    body { font-family: sans-serif; margin: 20px; background-color: #f4f4f4; }
    .container { max-width: 600px; margin: 0 auto; background-color: #fff; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
    h1 { text-align: center; color: #333; }
    form { display: flex; margin-bottom: 20px; }
    #add { flex-grow: 1; padding: 10px; border: 1px solid #ddd; border-radius: 4px 0 0 4px; font-size: 16px; }
    .addBtn { padding: 10px 15px; background-color: #007bff; color: white; border: none; border-radius: 0 4px 4px 0; cursor: pointer; font-size: 16px; }
    .addBtn:hover { background-color: #0056b3; }
    ul { list-style: none; padding: 0; }
    li { display: flex; justify-content: space-between; align-items: center; padding: 12px 15px; margin-bottom: 8px; background-color: #f9f9f9; border: 1px solid #eee; border-radius: 4px; transition: background-color 0.3s ease; }
    li button { padding: 8px 12px; background-color: #28a745; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; }
    li button:hover { background-color: #218838; }
    li button:disabled { background-color: #6c757d; cursor: not-allowed; }
  </style>
</head>
<body>
  <div class="container">
    <header>
      <p>
        <h1 id="title">Todo list</h1>
        <h2 id="date"></h2>
      </p>
      <form name="myForm" method="post" action="">
        <input type="text" id="add" name="addNew" placeholder="添加新任务...">
        <button name="sumbitBtn" type="button" class="addBtn" onclick="addItem()">add</button>
        <div>
          <ul id="unList">
          </ul>
        </div>
      </form>
    </header>
  </div>

  <script type="text/javascript">
  const list = [];

  function addItem() { 
    const taskInput = document.getElementById('add');
    const task = taskInput.value.trim(); 

    if (task === '') {
      alert('待办事项不能为空!');
      return;
    }

    list.push(task); 
    const unList = document.getElementById('unList');
    unList.innerHTML += `
      <li> 
        ${task} 
        <button type='button' onclick='changeBackgroundColor(this)'>done</button>
      </li>`;
    taskInput.value = '';
  } 

  function changeBackgroundColor(element) { 
     element.parentNode.style.backgroundColor = '#d4edda'; /* 浅绿色 */
     element.disabled = true;
     element.textContent = 'Done!';
     element.style.backgroundColor = '#28a745'; /* 按钮自身颜色 */
  }
  </script>
</body>
</html>

注意事项与最佳实践

  1. ID的唯一性: 再次强调,id 属性在HTML文档中必须是唯一的。对于需要动态操作的元素,如果无法保证ID的唯一性,应避免使用 document.getElementById()。
  2. DOM遍历的灵活性: 除了 parentNode,DOM还提供了 children、firstElementChild、lastElementChild、nextElementSibling、previousElementSibling 等属性,以及 closest()、querySelector() 等方法,可以帮助您在DOM树中灵活定位目标元素。
  3. 事件委托 (Event Delegation): 对于包含大量动态生成元素的列表,为每个元素单独绑定事件监听器可能会影响性能。更高效的做法是使用事件委托,即在父元素上绑定一个事件监听器,然后通过事件冒泡和 event.target 来判断是哪个子元素触发了事件。
  4. 样式与行为分离: 直接通过 element.style.propertyName 修改样式虽然直接,但在大型项目中,推荐通过添加或移除CSS类名的方式来改变元素样式。例如,可以定义一个 .completed 类,包含绿色的背景色,然后在 changeBackgroundColor 函数中通过 element.parentNode.classList.add('completed') 来添加这个类。这有助于保持CSS和JavaScript代码的整洁和可维护性。

总结

本教程详细讲解了如何在JavaScript中实现动态待办事项列表的背景色切换功能。核心在于理解 id 属性的唯一性原则,并掌握如何利用 this 关键字和 parentNode 属性进行精确的DOM操作。通过避免ID重复和采用正确的元素定位策略,您可以有效地管理和操作动态生成的Web页面内容,从而构建出更健壮、更具交互性的用户界面。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

761

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1568

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

651

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

1228

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

1204

2024.04.29

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

193

2025.07.29

c++字符串相关教程
c++字符串相关教程

本专题整合了c++字符串相关教程,阅读专题下面的文章了解更多详细内容。

131

2025.08.07

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.9万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.6万人学习

CSS教程
CSS教程

共754课时 | 43万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号