一. 本课目标
- 本次课程通过写一个命令行todo工具来学习node.js的文件模块。
- 需要注意package.json的依赖版本保持一致,这个很重要
{
"dependencies": {
"commander": "^3.0.2",
"inquirer": "^7.0.0"
}
}
二. 需求
- 功能
- 可以列出所有的todo
- 可以新增todo
- 可以编辑todo
- 可以删除todo
- 可以标记todo为已完成/未完成
- 命令
- t
- t add 任务名
- t clear
三. 会用到的一些库
commander
inquirer
winston
jest
四. 开始项目
- 创建一个空文件夹命名,就叫
x-node-todo,作为项目文件夹,用ws或vs打开 - 初始化项目,
yarn init -y,修改package.json的version成0.0.1 - 创建index.js,并随便写一句代码能运行
- 我们期望命令行运行
t -h的时候,出现一些效果,我们用commander.js来做
// 安装
yarn add commander
- 利用crm学习法,找到文档上的代码,抄袭
const program = require('commander');
program
.option('-d, --debug', 'output extra debugging')
.option('-s, --small', 'small pizza size')
.option('-p, --pizza-type <type>', 'flavour of pizza');
program.parse(process.argv);
- 此时运行
node index -h,会出现代码效果,之后我们去改代码
const program = require('commander');
program
.option('-x, --xx', 'what the x')
program.parse(process.argv);
- 再根据文档中提示发现opts()方法,改变代码
const program = require('commander');
program
.option('-x, --xxx', 'what the x')
program.parse(process.argv);
const options = program.opts();
console.log(options)
// 运行node index -x 打印出 {xxx: true}
- 继续在文档上找到声明子命令的地方,并同样进行crm,运行node index -h发现会有效果,以及能运行node index add
const program = require('commander');
program
.option('-x, --xxx', 'what the x')
program
.command('add taskName ')
.description('add a task')
.action(() => {
console.log('hi');
});
program.parse(process.argv);
- 在尝试把添加的任务名称打出来
const program = require('commander');
program
.option('-x, --xxx', 'what the x')
program
.command('add <taskName>')
.description('add a task')
.action((x) => {
console.log(x);
});
program.parse(process.argv);
const options = program.opts();
- 依样画葫芦添加clear
const program = require('commander');
program
.option('-x, --xxx', 'what the x')
program
.command('add <taskName>')
.description('add a task')
.action((x) => {
console.log(x);
});
program
.command('clear')
.description('clear all tasks')
.action((x) => {
console.log('this is clear')
});
program.parse(process.argv);
const options = program.opts();
五. 准备开始实现功能
- 修改index.js命名,命令行工具一般叫cli.js
- 新创建index.js,开始实现功能
module.exports.add = (title) => {
console.log('add', title)
}
- 此时cli.js引入index.js,开始调用其中方法,我们命令行运行
node cli.js add 'hi',能看到打印效果起手就算完成了
const program = require('commander');
const api = require('./index.js')
program
.option('-x, --xxx', 'what the x')
program
.command('add <taskName>')
.description('add a task')
.action((words) => {
console.log(words);
api.add(words)
});
program
.command('clear')
.description('clear all tasks')
.action((x) => {
console.log('this is clear')
});
program.parse(process.argv);
const options = program.opts();
六. 配置webstorm更优雅进行命令行调试
- 具体配置见下图,注意圈出的配置项
三. 尝试将数据持久化
- 不使用数据库,直接放到home目录的.todo文件里
- 初步完成代码逻辑
// 这是直接获取系统的home目录
const homedir = require('os').homedir();
// 这是用户设置的home目录环境变量
const home = process.env.HOME || homedir
// 拼接储存文件路径
const p = require('path')
const dbPath = p.join(home, '.todo')
const fs = require('fs')
module.exports.add = (title) => {
// console.log('add1', title)
console.log(home)
// 如果要添加新内容,要先读取之前的内容, a开头的用的比较多一点,后面x的是如果有文件就失败,比较少用
// a+ 表示没有就新建
fs.readFile(dbPath, { flag: 'a+' }, (error, data) => {
if(error) {
console.log('error', error)
}
else{
let list
try {
list = JSON.parse(data.toString())
console.log('list1', list)
} catch (error2) {
list = []
}
console.log('list2', list)
const task = {
title: title,
done: false
}
list.push(task)
console.log(list)
const string = JSON.stringify(list)
fs.writeFile(dbPath, string, (error3)=>{
if(error) {console.log(error3)}
})
}
})
// 往里面添加一个 title 任务
// 存储任务到文件
}