CYBERSWAT / 开发部自由练习 · v0.4.1

U02 · 删掉中间一本书,为什么改错了另一行

v0.4 · 先修:手册 08–14;工作台。选题参考:Odin Library。本节使用自己的虚构书目和原创练习。

做一个个人书库:记录标题、虚构作者和读完没有。第一版刷新后清空是已知边界;本节先解决页面和资料如何保持一致,不同时引入账号或数据库。

动手路线:每一步都有文件和结果

先完成 统一启动与恢复手册 的首次准备。以下命令均在自己的练习根目录执行;原文中的 api/web/desktop 概念对应本节列出的现成文件,不需要猜测如何搭空项目。

  1. 打开 u02/starter/model.ts,按 addBook → toggleRead → removeBook → unreadBooks 的顺序逐个实现。下面第1节起解释规则;每完成一个函数就重跑样例/测试。
  2. 执行以下三条,分别核对样例、行为和类型。未完成的 TODO 应失败,全部实现后测试应为 fail 0:
node tools/try.mjs u02
node tools/check.mjs u02
npm run check
  1. 打开 runtime/web/u02.js,找到对自己规则函数的调用。先用一句话记录输入从哪里来、结果写到哪里;读不懂的语法回到本节先修对应章节。

  2. 构建并启动自己的作品:

node tools/build-app.mjs u02
node tools/lab.mjs start u02
  1. 实际操作:添加甲、乙、丙三本书;删除乙,再切换丙的阅读状态。刷新后甲未读、丙已读;点击未读筛选只剩甲。

  2. 解释与再做一次:为什么列表位置不能作为图书身份?请指出事件里传递 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 将阅读状态换成不同的借用模型。