2Node.js文件模块学习开发命令行Todo工具(上)

73 阅读3分钟

一. 本课目标

  • 本次课程通过写一个命令行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更优雅进行命令行调试

  • 具体配置见下图,注意圈出的配置项

2-1.png

三. 尝试将数据持久化

  • 不使用数据库,直接放到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 任务
  // 存储任务到文件
}