U02 · 删掉中间一本书,为什么改错了另一行
v0.4 · 先修:手册 08–14;工作台。选题参考:Odin Library。本节使用自己的虚构书目和原创练习。
做一个个人书库:记录标题、虚构作者和读完没有。第一版刷新后清空是已知边界;本节先解决页面和资料如何保持一致,不同时引入账号或数据库。
动手路线:每一步都有文件和结果
先完成 统一启动与恢复手册 的首次准备。以下命令均在自己的练习根目录执行;原文中的 api/web/desktop 概念对应本节列出的现成文件,不需要猜测如何搭空项目。
- 打开
u02/starter/model.ts,按 addBook → toggleRead → removeBook → unreadBooks 的顺序逐个实现。下面第1节起解释规则;每完成一个函数就重跑样例/测试。 - 执行以下三条,分别核对样例、行为和类型。未完成的 TODO 应失败,全部实现后测试应为
fail 0:
node tools/try.mjs u02
node tools/check.mjs u02
npm run check
-
打开
runtime/web/u02.js,找到对自己规则函数的调用。先用一句话记录输入从哪里来、结果写到哪里;读不懂的语法回到本节先修对应章节。 -
构建并启动自己的作品:
node tools/build-app.mjs u02
node tools/lab.mjs start u02
-
实际操作:添加甲、乙、丙三本书;删除乙,再切换丙的阅读状态。刷新后甲未读、丙已读;点击未读筛选只剩甲。
-
解释与再做一次:为什么列表位置不能作为图书身份?请指出事件里传递 id 的位置。 在自己的 LEARNING.md 先写答案,再选本节末尾的变式,列一个新失败例子后修改。保持原用例通过。仅跑通配套界面、没有完成规则与解释,记录为“参考演示已观察”,不记录为自己完成作品。
卡在规则时按“函数输入→分支条件→返回值→参考实现”逐级看提示;卡在运行时按 故障表 定位。若想单独观察参考成品,在构建命令后加 --reference;页面会明确标出参考演示。观察完再去掉该参数重建,继续自己的 starter。
1. 从三本书开始
打开 u02/starter/model.ts,Book 的 id 与标题分开。sample.json 给出添加样例;测试中的 a/b/c 是三本书的稳定身份。画三张纸卡,删掉中间一张:第三本的位置变了,身份不应跟着变。
完成 addBook:标题与作者去空白,不能为空,编号不重复;同名不同编号允许保留。返回新数组。执行 node tools/try.mjs u02,应看到新增书目且 read 为 false。
2. 用编号操作,不用行号
完成 toggleRead、removeBook、unreadBooks。前两项找不到 id 时报告 NOT_FOUND;筛选结果为空时正常返回空数组。执行 node tools/check.mjs u02,重点读“删除中间行之后仍按稳定编号切换”。先预测再运行,说明为什么数组下标不能当永久 id。
3. 建立页面骨架
在自己的作品目录建 index.html、app.js,按手册 13/14 的原生页面方式加载脚本。页面有带 label 的书名/作者输入、添加按钮、“只看未读”复选框、列表和状态提示。先放三条合成资料,暂不接添加。
在 app.js 中手写对应 JS 规则,去掉 TS 类型标注;保留已完成的 TS 核心和测试。render 每次从 books 重建列表,把 id 放进按钮的 data-id,标题用 textContent。先验证尖括号标题按文字显示。
4. 沿着一次点击检查流程
表单 submit 中阻止默认导航,读输入,调用 addBook,成功才清空表单并 render;失败在提示区解释,原列表保留。编号使用浏览器 crypto.randomUUID,若环境不提供,先按手册开发服务器在本机运行,不把数组长度当替代编号。
给每行添加“读完/未读”与删除按钮。事件读取 data-id,先更新 books,再 render。过滤只影响显示数组,不能把筛选结果覆盖为全部 books。输入回车和鼠标点击应走同一条路径。
5. 重现题目中的故障
加甲乙丙三本,删乙,再切换丙。预期甲未读、丙已读;勾选只看未读后只剩甲,取消筛选后丙仍在。若丙状态改错,先查按钮保存的是 id 还是当前行下标;若取消筛选找不回丙,查是否覆盖了原数组。
6. 自检、暂停与继续
| 检查 | 预期 |
|---|---|
| 空作者/全空格标题 | 明确拒绝,列表不变 |
| 同标题两本 | 可以分别修改,不混淆 |
| 键盘 Tab 与回车 | 可完成添加和按钮操作,焦点可见 |
| 没有未读书 | 显示空状态,不显示假错误 |
| 刷新 | 第一版恢复空列表;README 如实说明 |
独立变式:增加“全部/已读/未读”三种显示模式,先写三本书的预期集合,再实现;不要新增第二份手工维护的未读数量。可选保存版放在此后:写 localStorage 时记录格式版本,读取失败不清空旧数据。保存版不是本节基础完成的前置。
完成类型检查、核心测试和以上页面操作后记录;关闭页面即可暂停。参考核心不含 DOM 实现,也未证明你的键盘体验。下一步 U03,后续 U05 将阅读状态换成不同的借用模型。