综合练习与下一步
小项目清单、React/Node 路线指引。
45 分钟
综合练习与下一步
这一课你将能做到
- 独立做一页「学习清单」小工具(增、删、切换完成状态)
- 对照清单自检:变量、函数、数组、DOM、基础错误处理都用到了
- 选准下一门课(TypeScript 或 React),并写下自己的薄弱点复习计划
为什么要学
前面每课都是零件:变量、函数、数组、对象、DOM、异步、模块、调试。
若不串成一个小作品,知识会停在「好像看过」。
这一课强制你手写。
能独立做完清单工具,再上 React/TS 时,你会知道框架到底替你省了哪一步。
先建立图像
数据(唯一真相)
items = [{ id, title, done }, ...]
↓ 每次变更后
render()
↓
DOM 列表(只是投影)
| 操作 | 改数据 | 然后 |
|---|---|---|
| 添加 | push 新对象 | render |
| 完成 | 找到项,翻 done | render |
| 删除 | filter/splice | render |
别走「只改 DOM、不管数组」的路线——状态会很快不一致。
跟着做
步骤 1:搭页面骨架
新建 study-list.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>学习清单</title>
<style>
body { font-family: sans-serif; max-width: 480px; margin: 24px auto; padding: 0 12px; }
.done { text-decoration: line-through; opacity: 0.6; }
.err { color: #b91c1c; }
li { margin: 8px 0; }
</style>
</head>
<body>
<h1>学习清单</h1>
<input id="title" type="text" placeholder="例如:复习数组 map" />
<button type="button" id="add">添加</button>
<p id="hint" class="err" hidden></p>
<ul id="list"></ul>
<script src="./study-list.js"></script>
</body>
</html>
先用浏览器打开,确认标题与输入框在;控制台暂无报错(脚本文件下一步创建)。
步骤 2:建立数据与 render
新建同目录 study-list.js:
// 数据:唯一真相
const items = []; // { id: number, title: string, done: boolean }
const listEl = document.getElementById("list");
const hintEl = document.getElementById("hint");
const inputEl = document.getElementById("title");
function showHint(msg) {
if (!msg) {
hintEl.hidden = true;
hintEl.textContent = "";
return;
}
hintEl.hidden = false;
hintEl.textContent = msg;
}
function render() {
listEl.replaceChildren();
for (const item of items) {
const li = document.createElement("li");
if (item.done) li.classList.add("done");
const span = document.createElement("span");
span.textContent = item.title;
li.appendChild(span);
const toggle = document.createElement("button");
toggle.type = "button";
toggle.textContent = item.done ? "标为未完成" : "完成";
toggle.dataset.action = "toggle";
toggle.dataset.id = String(item.id);
const del = document.createElement("button");
del.type = "button";
del.textContent = "删除";
del.dataset.action = "delete";
del.dataset.id = String(item.id);
li.append(" ", toggle, " ", del);
listEl.appendChild(li);
}
}
render(); // 初始为空列表也要跑通