太棒了!👏 我们现在进入下一个实战项目:
📌 目标:
做一个能在终端运行的 Todo CLI 工具,支持以下命令:
todo add "学习 Node.js"
todo list
todo done 0
todo delete 0
数据保存在本地 todos.json 文件中,像一个轻量级“数据库”。
📁 项目结构
todo-cli/
├── todos.json ← 存储任务数据
├── todo.js ← 主程序
└── package.json ← 可执行脚本配置
✅ 第一步:初始化项目
mkdir todo-cli
cd todo-cli
npm init -y
✅ 第二步:创建 todos.json
新建文件,初始内容为一个空数组:
[]
✅ 第三步:编写 todo.js
// todo.js
const fs = require('fs');
const path = require('path');
// 数据文件路径
const dataFile = path.join(__dirname, 'todos.json');
// 读取所有任务
function loadTodos() {
try {
const data = fs.readFileSync(dataFile, 'utf8');
return JSON.parse(data);
} catch (err) {
return [];
}
}
// 保存所有任务
function saveTodos(todos) {
fs.writeFileSync(dataFile, JSON.stringify(todos, null, 2));
}
// 获取命令和参数
const [command, ...args] = process.argv.slice(2);
// 主逻辑
if (command === 'add') {
const text = args.join(' ');
if (!text) {
console.log('❌ 请写下你要做的事!');
process.exit(1);
}
const todos = loadTodos();
todos.push({
id: Date.now(), // 用时间戳做唯一 ID
text,
done: false,
createdAt: new Date().toLocaleString()
});
saveTodos(todos);
console.log(`✅ 已添加: "${text}"`);
}
else if (command === 'list') {
const todos = loadTodos();
if (todos.length === 0) {
console.log('📝 暂无任务');
process.exit(0);
}
console.log('\n📋 待办事项列表:\n');
todos.forEach((todo, index) => {
const status = todo.done ? '✅' : '⭕';
console.log(`${index}. [${status}] ${todo.text} (${todo.createdAt})`);
});
}
else if (command === 'done') {
const index = parseInt(args[0]);
const todos = loadTodos();
if (isNaN(index) || index < 0 || index >= todos.length) {
console.log('❌ 无效的任务序号!');
} else {
todos[index].done = true;
saveTodos(todos);
console.log(`🎉 任务完成: "${todos[index].text}"`);
}
}
else if (command === 'delete') {
const index = parseInt(args[0]);
const todos = loadTodos();
if (isNaN(index) || index < 0 || index >= todos.length) {
console.log('❌ 无效的任务序号!');
} else {
const deleted = todos.splice(index, 1);
saveTodos(todos);
console.log(`🗑️ 已删除: "${deleted[0].text}"`);
}
}
else {
console.log(`
📌 使用说明:
todo add "内容" → 添加任务
todo list → 查看所有任务
todo done <序号> → 标记完成
todo delete <序号> → 删除任务
`);
}
✅ 第四步:让 todo 成为全局命令
我们希望可以直接运行:
todo list
而不是:
node todo.js list
方法:使用 bin 字段
修改 package.json:
{
"name": "todo-cli",
"version": "1.0.0",
"description": "命令行待办事项工具",
"main": "todo.js",
"bin": {
"todo": "./todo.js"
},
"scripts": {
"start": "node todo.js"
},
"keywords": ["cli", "todo"],
"author": "Your Name",
"license": "MIT"
}
📌 关键是 "bin" 字段:它告诉 npm 把 todo 命令指向 ./todo.js
✅ 第五步:安装为全局命令
在项目根目录运行:
npm install -g .
-g . 表示“全局安装当前项目”
🏃♂️ 第六步:测试你的 CLI 工具!
现在你可以在任何地方运行:
添加任务
todo add "学习 Node.js 模块系统"
输出:
✅ 已添加: "学习 Node.js 模块系统"
查看列表
todo list
输出:
📋 待办事项列表:
0. [⭕] 学习 Node.js 模块系统 (2025/4/5 14:30:00)
标记完成
todo done 0
输出:
🎉 任务完成: "学习 Node.js 模块系统"
再次查看
todo list
会显示 ✅ 完成状态!
✅ 小结一句话:
我们用 fs + process.argv + package.json 的 bin 字段,打造了一个真正可用的命令行工具,可以全局调用,数据持久化存储。
💡 学到了什么?
| 技术点 | 说明 |
|---|---|
process.argv.slice(2) | 获取用户输入的命令 |
fs 读写 todos.json | 数据持久化 |
bin 字段 | 将 JS 文件注册为系统命令 |
npm install -g . | 全局安装本地包 |
| CLI 设计模式 | 简洁、直观、高效 |
📬 最后一课预告:
第 22 课:课程总结 + 下一步学习建议(全栈、数据库、部署等)
我们将回顾整个学习路径,并告诉你:
- 学完 Node.js 后该学什么?
- 如何连接 MongoDB 或 MySQL?
- 如何把项目部署到线上?
准备收尾并迈向更高阶了吗?🙂
回复 “继续” 进入最终章!🎓🚀