JavaScript: 综合项目:待办清单

恭喜你走到了最后一课!前面的 27 课你学到了变量、函数、数组、DOM、事件、JSON、异步、Class……现在该把它们串起来,做一个完整的小应用了。这个项目将是你学习成果的集大成之作。


1. 项目介绍

我们将开发一个待办清单(Todo App)——别看它小,它几乎用到了你学过的所有核心知识。完成后你会有一个可以真正使用的效率工具。



▶ 示例

JAVASCRIPT
// 本节代码示例
const message = "你好,世界!";
console.log(message);
▶ 试一试

这是最简单的示例,后续章节会详细解释。## 2. 功能需求

  1. 添加待办事项 — 输入框 + 按钮,回车或点击都能添加
  2. 标记完成/未完成 — 点击待办项切换完成状态(划线效果)
  3. 删除待办事项 — 每项旁有删除按钮
  4. 筛选 — 三个按钮:全部 / 未完成 / 已完成
  5. 本地存储 — 用 localStorage 保存数据,刷新页面不丢失
  6. 统计未完成数量 — 底部显示"X 项未完成"


3. 技术要求

知识点 用在哪
Class TodoApp 类组织所有逻辑
async/await localStorage 的读写操作包装成异步函数
DOM 操作 动态创建列表项、修改内容、删除元素
事件处理 表单 submit、列表 click、筛选按钮 click
JSON JSON.stringify 保存、JSON.parse 读取
数组方法 filtermapfind 操作待办数据
模板字符串 拼接 HTML


4. 验收标准



5. 参考实现思路

以下是提示和方向,不是完整代码。自己动手写出来,收获才最大。

(1) 数据结构

HTML
<script>
// 每个待办项是一个对象
const todo = {
  id: Date.now(),      // 唯一标识
  text: '学习 JavaScript',
  completed: false
};
console.log(todo);

// 所有待办项存在数组中
let todos = [];
</script>

(2) 类结构

HTML
<script>
class TodoApp {
  constructor() {
    this.todos = [];         // 数据
    this.filter = 'all';     // 当前筛选
    this.init();             // 初始化
  }

  async init() {
    // 1. 从 localStorage 加载数据
    // 2. 绑定事件
    // 3. 渲染列表
  }

  async save() {
    // JSON.stringify → localStorage.setItem
  }

  async load() {
    // localStorage.getItem → JSON.parse
  }

  addTodo(text) { /* 创建对象,push,save,render */ }
  toggleTodo(id) { /* 找到对应项,取反 completed,save,render */ }
  deleteTodo(id) { /* 过滤掉对应项,save,render */ }

  render() {
    // 1. 根据 filter 筛选 todos
    // 2. 清空列表容器
    // 3. 遍历筛选后的数组,创建 DOM
    // 4. 更新统计数字
  }
}
</script>

(3) 事件绑定思路

(4) 渲染思路

HTML
<script>
render() {
  const filtered = this.todos.filter(function(todo) {
    if (this.filter === 'active') return !todo.completed;
    if (this.filter === 'completed') return todo.completed;
    return true;  // 'all'
  }.bind(this));

  // 清空容器
  this.listEl.innerHTML = '';

  filtered.forEach(function(todo) {
    var li = document.createElement('li');
    // 设置内容、样式、数据属性
    // 绑定完成和删除的事件
    this.listEl.appendChild(li);
  }.bind(this));

  // 更新统计
  var activeCount = this.todos.filter(function(t) { return !t.completed; }).length;
  this.countEl.textContent = activeCount + ' 项未完成';
}
</script>


6. 拓展方向

完成基本功能后,试试这些进阶挑战:


▶ 示例

使用类和 localStorage 的完整 Todo 应用:

HTML
<!DOCTYPE html>
<html>
<head><style>body{font-family:Arial;max-width:600px;margin:20px auto;}.done{text-decoration:line-through;color:gray;}</style></head>
<body>
  <h1>Todo 应用</h1>
  <input id="taskInput" placeholder="新任务">
  <button id="addBtn">添加</button>
  <ul id="taskList"></ul>
  <script>
    class Todo {
      constructor() { this.tasks = JSON.parse(localStorage.getItem('tasks') || '[]'); }
      add(text) { this.tasks.push({text, done: false}); localStorage.setItem('tasks', JSON.stringify(this.tasks)); this.render(); }
      toggle(i) { this.tasks[i].done = !this.tasks[i].done; localStorage.setItem('tasks', JSON.stringify(this.tasks)); this.render(); }
      render() { document.getElementById('taskList').innerHTML = this.tasks.map((t, i) => `<li class="${t.done ? 'done' : ''}">${t.text}</li>`).join(''); }
    }
    const todo = new Todo();
    document.getElementById('addBtn').onclick = () => todo.add(document.getElementById('taskInput').value);
    todo.render();
  </script>
</body>
</html>
▶ 试一试

这演示了基于类的状态管理、localStorage 持久化、动态 DOM 渲染的完整 Todo 应用。


❓ 常见问题

Q 为什么用 Class 而不是构造函数?
A Class 语法更清晰简洁,constructorthis、继承都有明确的语法支持。虽然底层仍然是原型链,但写起来像其他面向对象语言,可读性更好。
Q localStorage 存储的数据会丢失吗?
A 除非用户手动清除浏览器数据或使用无痕模式,否则 localStorage 的数据会永久保存在本地。注意它只能存字符串,对象需要 JSON.stringify 后再存。
Q 事件委托是什么?为什么在待办清单中特别有用?
A 事件委托是把事件监听器绑在父元素上,通过判断 e.target 来处理子元素的事件。在待办清单中,新增的待办项自动获得事件处理,不用重复绑定,性能更好。

📖 小节

📝 作业

完成上述待办清单应用的所有功能,并通过所有验收标准。

建议步骤:

  1. 先搭 HTML 结构和 CSS 样式
  2. 实现 TodoApp 类的骨架(constructorinit
  3. 实现 addTodorender,先让添加功能跑通
  4. 实现 toggleTodo,标记完成/未完成
  5. 实现 deleteTodo,删除功能
  6. 实现筛选功能
  7. 实现 saveload,持久化数据
  8. 统计未完成数量
  9. 最后打磨:空输入提示、样式优化
💡 提示: 别想一步到位,先让最小功能跑起来,再一点点加。软件开发就是"先让它工作,再让它好看,最后让它快"。


📝 作业

  1. 基础:完成待办清单的核心功能——添加、标记完成、删除,数据用数组存储即可(无需 localStorage)。
  2. 进阶:在基础版上加入 localStorage 持久化和筛选功能(全部/未完成/已完成),刷新后数据不丢失。
  3. 挑战:实现拓展功能中的至少一项(拖拽排序、编辑功能、分类标签、主题切换或到期提醒),并写出实现思路说明。
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏