生活分享
实作功能:完成待办筛选
从 start 材料补上 Active/Completed 筛选,保留资料格式并用正常与边界案例验收。
阅读时间约 14 分钟 · 操作 30 分钟

返回 Codex 教学总目录Codex 学习中心:完整教程目录从安装、第一个任务到 MD 规则与进阶集成,规划 60 篇 Codex 教程、十个单元。按程度、平台、需求或命令搜索下一篇;尚未公开的教程会标示状态,方便安排学习路线。阅读全文
目标与准备
本段提到的教学与资源: 专案阅读先读懂一个既有专案用唯读流程找到启动点、资料流与测试,产生有档案依据的专案地图。阅读全文
Plan 模式篇Plan 模式:先规划再实现Plan 模式适合还需要决定范围或做法的工作。它帮你把需求整理成可实作的计划,但计划本身不是已完成的程式。使用时先定义要讨论的问题,再检查计划是否包含输入、输出、限制与验证。阅读全文练习审阅与交付计划;这篇把焦点放在功能从失败到完成的证据。题目相同,验收更深入:不能只看画面剩一列就说筛选成功,还要证明被隐藏的资料没有被删除、排序不变,两个相同标题仍能依识别码正确处理。
步骤 1:从未完成版本建立基准
从练习 ZIP 的 start 复制五个档案到新的 codex-feature-lab,不沿用已完成的 expected,也不把前一篇修好的 core.mjs 带进来。开启资料夹后确认路径;PowerShell 用 Get-Location,macOS/Linux 用 pwd。保留 start 原版,先跑下列既有测试,预期 2 项通过、1 项筛选失败。
node --test core.test.mjs
先读 index.html 的选项与 app.js 的 filter change 事件,确认控制项已经存在。缺少的是 visibleTasks 的行为,不需要重写 UI 或安装框架。这也是先读专案的价值:档案名称看起来像前端,不代表所有变更都要从画面开始。将既有失败结果记在笔记,后续不能靠删测试改写成功。
步骤 2:用案例固定完成条件
将下列三个验收测试存为根目录 filter.test.mjs。它是本篇新增的测试档,不覆盖 core.test.mjs。第一个用 a 与 c 两个同名 Read,确认完成筛选保留两个识别码且顺序相同;第二个确认 All 没丢资料;第三个涵盖三种空清单。冻结输入会让不当原地修改更容易被抓出来。
import test from "node:test";
import assert from "node:assert/strict";
import { visibleTasks } from "./core.mjs";
const tasks = Object.freeze([
Object.freeze({ id: "a", title: "Read", completed: true }),
Object.freeze({ id: "b", title: "Build", completed: false }),
Object.freeze({ id: "c", title: "Read", completed: true }),
]);
const ids = (items) => items.map((item) => item.id);
test("filters preserve identity and order with duplicate titles", () => {
assert.deepEqual(ids(visibleTasks(tasks, "active")), ["b"]);
assert.deepEqual(ids(visibleTasks(tasks, "completed")), ["a", "c"]);
assert.deepEqual(ids(tasks), ["a", "b", "c"]);
});
test("All retains every task without changing its completion state", () => {
assert.deepEqual(ids(visibleTasks(tasks, "all")), ["a", "b", "c"]);
assert.deepEqual(tasks.map((task) => task.completed), [true, false, true]);
});
test("every filter accepts an empty list", () => {
for (const filter of ["all", "active", "completed"]) {
assert.deepEqual(visibleTasks(Object.freeze([]), filter), []);
}
});
node --test core.test.mjs filter.test.mjs
在 start 起点,合并执行应是 4 过、2 败:既有筛选测试与新第一项测试会失败,All 和空阵列本来就通过。这让你知道新测试确实能抓到缺少筛选的问题。若出现语法错误或找不到档案,先修正储存位置与复制内容;它们不是预期的功能失败,不能混成同一个红灯。
步骤 3:实作最小功能
桌面版加入 codex-feature-lab 为本机专案并建立新任务;CLI 从此练习目录执行 codex。确认任务路径后,贴上完整要求。这时原始程式只有 core.mjs 可修改,新增的 filter.test.mjs 内容也已经固定。若模型认为需要其他档案,先请它指出具体原因;不要一开始就让它把所有测试、画面与设定一起「整理」。没有读到测试时,要求先读,避免只照自然语言猜测。
Implement the missing filters in this codex-feature-lab.
Read index.html, app.js, core.mjs, core.test.mjs and filter.test.mjs first.
Modify only visibleTasks in core.mjs: all keeps every task, active returns unfinished tasks, completed returns finished tasks. Preserve original order, IDs and input data. Do not edit tests, add dependencies or change UI/storage.
Run node --test core.test.mjs filter.test.mjs. Inspect the final diff and report actual results and any unperformed browser checks. Stop and explain if the requested scope cannot satisfy the tests. Do not publish or deploy.
参考实作如下。filter 产生符合条件的新阵列,里面仍引用原任务物件;这个函式只挑选,不修改物件,因此符合本题要求。All 可以回传原阵列,不必为了看起来「更安全」进行没有必要的深层复制。使用 !task.completed 与 task.completed 的差别要能自己读懂,不能只认测试变绿。
export function visibleTasks(tasks, filter) {
if (filter === "active") return tasks.filter((task) => !task.completed);
if (filter === "completed") return tasks.filter((task) => task.completed);
return tasks;
}
步骤 4:验收资料、画面与范围
重跑同一条测试命令,参考修正预期 6 项全过。接著核对差异:原本五个档案只改了 core.mjs,另外多一个你新增的 filter.test.mjs。若测试 assertions 被删除,先恢复固定测试再跑;若增加无关档案,逐一检查来源,不能因为成功摘要漂亮就忽略范围。修改完成与验收完成分开记录。
从 codex-feature-lab 启动 Python HTTP 预览,Windows 用 py -m http.server 4173 --bind 127.0.0.1,macOS/Linux 用 python3 代替 py,浏览器开 http://127.0.0.1:4173。先处理自己原有预览的埠占用,不停其他服务。直接双击 HTML 可能因模组限制载入失败;若看到旧画面,确认伺服器目录及重新整理后再判断。
先保留仍需要的旧练习纪录,再于 About this exercise 使用 Reset practice data。选 All tasks 并确认空清单后,依序加入 Read、Build、Read,勾选第一与第三项。照表切换,再回 All 确认三笔都在;同名项目以原先位置与勾选状态辨认。取消第一项完成后,Completed 应只剩原第三项,Active 应保留原第一项与 Build。最后切回 All 重新整理,确认状态仍在。
| 检查点 | All | Active | Completed |
|---|---|---|---|
| 原第一、第三项完成 | Read、Build、Read | Build | Read、Read |
| 原第一项取消完成 | Read、Build、Read | Read、Build | 原第三项 Read |
| 清空教材任务后 | 空 | 空 | 空 |
反例验证:全数计数与同名任务
画面练习中,Read、Build、Read 共三笔,第一和第三笔完成时,All/Active/Completed 的列数分别为 3/1/2,但三种画面的计数都应是 1 active / 3 total。取消第一笔完成后,三种列数变成 3/2/1,计数都为 2 active / 3 total。app.js 用完整 tasks 计数;只通过核心筛选测试不能证明画面计数正确,请另记实际结果。
六项测试通过后,先把修好的 core.mjs 复制到练习资料夹外保存。在练习版只暂时把 Completed 分支替换成下面的错误写法,再跑原两个测试档。它先按完成状态筛选,再按 title 去重,会遗失 ID c;预期 5 过 1 败。原三项测试单独跑仍全过,因为其两笔资料没有同名。读出失败的实际 ID 后,立刻用刚才保存的修正版恢复 core.mjs,应回到 6 过 0 败;测试档保持不变。
if (filter === "completed") return tasks.filter((task) => task.completed).filter((task, index, selected) => selected.findIndex((other) => other.title === task.title) === index);
若反例没有失败,先确认有执行 filter.test.mjs、第三笔仍为不同 ID 的 Read,以及正在测试修改过的副本。若变成语法或找不到模组错误,先恢复档案再核对替换位置;那不是成功抓到去重缺陷。这个反例只检查测试覆盖,不需要改 UI 或提交错误版本。
失败排除、交付与还原
筛选时资料真的少了,先看是否错把 filter 结果写回 tasks 或保存;画面数量对但同名任务不对,要检查是否用 title 代替 id。核心全过但画面无变,先读 app.js 是否载入正确 core.mjs,并核对 HTTP 来源与浏览器快取。不要连续要求「再修一次」却不提供哪个表格列失败,先把重现顺序与预期写清楚。
交付应包含六项测试摘要、画面案例、最终差异,以及没有操作的检查清单。重做时停止预览,只从 start 还原 core.mjs;若保留新测试,应回到 4 过 2 败,若只执行旧测试,则是 2 过 1 败。保留两个命令的差别,避免把测试数量不同误当另一个故障。图中 1 是固定案例,2 是限定修改,3 是回归与还原。这些是可执行参考材料,不是声称已替你执行 Codex 任务。
返回 Codex 教学总目录Codex 学习中心:完整教程目录从安装、第一个任务到 MD 规则与进阶集成,规划 60 篇 Codex 教程、十个单元。按程度、平台、需求或命令搜索下一篇;尚未公开的教程会标示状态,方便安排学习路线。阅读全文
阅读完整文字说明
Three numbered stages: identify the starting point, perform the exercise, and verify the result. Original illustration, not a product screenshot.


同主题延伸阅读
生活分享
Codex 学习中心:完整教程目录
从安装、第一个任务到 MD 规则与进阶集成,规划 60 篇 Codex 教程、十个单元。按程度、平台、需求或命令搜索下一篇;尚未公开的教程会标示状态,方便安排学习路线。
生活分享
Worktree 与多任务隔离
Worktree 让同一个 Git 程式库有不同的工作目录,各自承接不同分支。它适合让两项工作分开改档,但资料库、连接埠与外部服务仍可能共用,不能把档案隔离当成所有资源隔离。
生活分享
实战:制作小网站
从 brief.md 规划并制作 Small Steps 待办网站,完成新增、完成、删除、筛选与本机资料保存。将 HTML、CSS、资料函式、画面事件与测试分开,以 Node 测试和浏览器操作验收,并留下可重新启动与还原的交接纪录。
生活分享
用量与效率:减少重工
记录任务条件、模型选项、时间与成果,找出能减少无效重试和过多上下文的调整。
引用本文的文章
最新旅游情报攻略

攻略东京
东京住哪一区:新宿、上野、东京站、涩谷、浅草、池袋、银座七区比较,机场交通、住宿税、行李寄送一次看
东京住哪一区?用同一套标准比较新宿、上野、东京站、涩谷、浅草、池袋、银座七个区域:从成田、羽田机场怎么过来、有哪些线路、周边有什么、街区氛围、适合谁。附比较表与山手线示意图,以及 2026 年 9 月核实的东京都住宿税(2027 年 4 月改为 3%)和机场宅急便寄送行李的规则。
- 预算
- 酒店

攻略东京
东京交通票券怎么选:Suica/Welcome Suica、Tokyo Subway Ticket、JR Pass 值不值得买
第一次去东京,每人先用一张 IC 卡按次付费(Welcome Suica 免押金、有效期 28 天)。一天搭四趟以上地铁,再加买 2,000 日元的 Tokyo Subway Ticket 72 小时券;只玩东京、不去关西,买 JR Pass 一定不划算。用决策图比较 TOURIST PASMO、iPhone 里的 Suica、东京 Metro 一日券能搭什么、不能搭什么;价格于 2026 年 9 月核实。
- 交通
- 预算

攻略东京
东京迪士尼乐园、海洋攻略:票价、梦幻泉乡 Fantasy Springs、尊享卡 DPA 与预约等候卡怎么用,第一次去选哪个园区
东京迪士尼一日护照采用浮动票价,2026 年 9 月平日大多为 9,900 日元、周末为 10,900 日元,官网每天 14:00 开售两个月后同一天的门票;免费的优先通行卡已不在官网服务清单,缩短排队时间只剩付费的迪士尼尊享卡(每人每次 1,000 至 3,500 日元)。另有运营时间与 25 周年活动、预约等候卡与报名体验、梦幻泉乡如何进入,以及第一次去选乐园还是海洋;2026 年 9 月通过东京迪士尼度假区官网核实。
- 行程范例
- 亲子