实现一个简单的 node 应用之 todo list2

简介: 实现一个简单的 node 应用之 todo list2

五、inquirer

inquirer 是一个用户与命令行交互工具。github.com/SBoudrias/I…

1. 安装依赖

yarn add inquirer

当展示出所有的任务后,实际上需要上下移动光标,然后执行后续的操作,因此就要借助 inquirer 库来实现这个目标!

2. 操作任务(功能 4)

// index.js
const db = require('./db');
const inquirer = require('inquirer');
// 添加新任务
module.exports.add = async (taskContent) => {
  // 1.读取文件
  const list = await db.read();
  // 2.添加一个任务
  list.push({title: taskContent, completed: false});
  // 3.将任务写入文件
  await db.write(list);
}
// 清空任务列表
module.exports.clear = async () => {
  await db.write([]);
}
// 展示所有事项
module.exports.showAll = async () => {
  // 1. 读出之前的任务
  const list = await db.read();
  // 2. 打印之前的任务
  // list.forEach((task, index) => {
  //   console.log(`${task.completed ? '[x]' : '[_]'} ${index + 1} -> ${task.title}`);
  // });
  // 发起询问
  inquirer
    .prompt({
        type: 'list',
        name: 'index',
        message: '你想要执行哪一项任务?',
        choices: [
          { name: '+ 添加任务', value: '-2'},
          { name: '- 退出', value: '-1'},
          ...list.map((task, index) => {
            return { name: `${task.completed ? '[x]' : '[_]'} ${index + 1} -> ${task.title}`, value: index }
          })
        ],
      })
    .then((answer) => {
      const index = parseInt(answer.index);
      if (index >= 0) {
        // 选中了一个任务
        inquirer.prompt({
          type: 'list',
          name: 'action',
          message: '请选择操作',
          choices: [
            {name: '退出', value: 'quit'},
            {name: '已完成', value: 'completed'},
            {name: '未完成', value: 'incomplete'},
            {name: '改标题', value: 'updateTitle'},
            {name: '删除', value: 'remove'},
          ]
        }).then(answer => {
          console.log(answer.action);
          switch (answer.action) {
            case 'completed':
              list[index].completed = true;
              db.write(list)
              break;
            case 'incomplete':
              list[index].completed = false;
              db.write(list)
              break;
            case 'updateTitle':
              inquirer.prompt({
                type: 'input',
                name: 'title',
                message: '请输入新的标题',
                default: list[index].title // 原标题
              }).then(answer => {
                list[index].title = answer.title;
                db.write(list);
              });
              break;
            case 'remove':
              list.splice(index, 1);
              db.write(list);
              break;
          }
        })
      } else if (index === -2) {
        // 添加任务
        inquirer.prompt({
          type: 'input',
          name: 'title',
          message: '请添加新任务标题',
        }).then(answer => {
          list.push({
            title: answer.title,
            completed: false
          })
          db.write(list);
        })
      }
    });
}


12.jpg


3. 代码优化

// index.js
const db = require('./db');
const inquirer = require('inquirer');
// 1. 添加新任务
module.exports.add = async (taskContent) => {
  // 1.读取文件
  const list = await db.read();
  // 2.添加一个任务
  list.push({title: taskContent, completed: false});
  // 3.将任务写入文件
  await db.write(list);
}
// 2. 清空任务列表
module.exports.clear = async () => {
  await db.write([]);
}
// 3.2.2 添加新任务
function askForAddNewTask (list) {
  inquirer.prompt({
    type: 'input',
    name: 'title',
    message: '请添加新任务标题',
  }).then(answer => {
    list.push({
      title: answer.title,
      completed: false
    })
    db.write(list);
    console.log('添加成功!');
  })
}
// 3.2.1.1 设置已完成状态
async function setCompletedState (list, index) {
  list[index].completed = true;
  await db.write(list);
  console.log('当前任务已完成!');
}
// 3.2.1.2 设置未完成状态
async function setIncompleteState (list, index) {
  list[index].completed = false;
  await db.write(list);
  console.log('当前任务待完成...');
}
// 3.2.1.3 修改标题
function updateTitle (list, index) {
  inquirer.prompt({
    type: 'input',
    name: 'title',
    message: '请输入新的标题',
    default: list[index].title // 原标题
  }).then(answer => {
    list[index].title = answer.title;
    db.write(list);
    console.log('标题更新成功!');
  });
}
// 3.2.1.4 移除任务
async function removeTask (list, index) {
  list.splice(index, 1);
  await db.write(list);
  console.log('删除成功!');
}
// 3.2.1 后续操作
function askForNextAction (list, index) {
  const actions = {
    setCompletedState,
    setIncompleteState,
    updateTitle,
    removeTask
  }
  inquirer.prompt({
    type: 'list',
    name: 'action',
    message: '请选择操作',
    choices: [
      {name: '退出', value: 'quit'},
      {name: '已完成', value: 'setCompletedState'},
      {name: '未完成', value: 'setIncompleteState'},
      {name: '改标题', value: 'updateTitle'},
      {name: '删除', value: 'removeTask'},
    ]
  }).then(answer => {
    const currentAction = actions[answer.action];
    currentAction && currentAction(list, index);
    // switch (answer.action) {
    //   case 'setCompletedState':
    //     setCompletedState(list, index);
    //     break;
    //   case 'setIncompleteState':
    //     setIncompleteState(list, index);
    //     break;
    //   case 'updateTitle':
    //     updateTitle(list, index);
    //     break;
    //   case 'removeTask':
    //     removeTask(list, index);
    //     break;
    // }
  })
}
// 3.2 打印之前的任务 + 后续操作
function displayTasks (list) {
  inquirer
  .prompt({
      type: 'list',
      name: 'index',
      message: '你想要执行哪一项任务?',
      choices: [
        { name: '+ 添加任务', value: '-2'},
        { name: '- 退出', value: '-1'},
        ...list.map((task, index) => {
          return { name: `${task.completed ? '[x]' : '[_]'} ${index + 1} -> ${task.title}`, value: index }
        })
      ],
    })
  .then((answer) => {
    const index = parseInt(answer.index);
    if (index >= 0) {
      // 3.2.1 选中了一个任务,执行后续操作
      askForNextAction(list, index);
    } else if (index === -2) {
      // 3.2.2 添加新任务
      askForAddNewTask(list);
    }
  });
}
// 3. 展示所有事项
module.exports.showAll = async () => {
  // 3.1 读出之前的任务
  const list = await db.read();
  // 3.2 打印之前的任务
  displayTasks(list);
}


六、代码发布

1. 设置 shebang

让用户自动执行 node,参考:zhuanlan.zhihu.com/p/262456371

在 cli.js 中的首行添加一段 shebang 代码:

// cli.js
#!/usr/bin/env node

2. 配置 package.json

{
  "name": "cpc-node-todo-1",
  "bin": {
    "cpc-todo": "./cli.js"
  },
  "files": [
    "cli.js",
    "db.js",
    "index.js"
  ],
  "version": "0.0.3",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "commander": "^8.0.0",
    "inquirer": "^8.1.2"
  }
}
  • name 字段表示,包的名称,以后通过这个名称来下载使用。
  • bin 字段表示,以后用户在终端中可直接运行的命令。


13.jpg


  • files 字段表示,需要打包上传的文件。这里是 cli.js、index.js、db.js 三个文件,当然如果说,你的目录里就只有这三个 js 文件的话,那么该字段就可以直接写成: "files": ["*.js"]

3. 发布到 NPM

  1. 1.npm login (此步骤需要填写用户名和密码,以及邮箱。)
  2. 2.npm publish
  3. 3.npm logout

4. 下载使用

  1. 1.打开终端,全局安装:npm i -g cpc-node-todo-1
  2. 2.安装好后,通过 cpc-todo 来调用这个 node 应用,注意这个 cpc-todo 就是打包之前 package.json 中设置的 bin 字段的内容。


14.jpg


  1. 3.如果不想用了,通过以下命令来卸载即可: npm un -g cpc-todo-1

5. 包的更新

略。


七、单元测试

1. jest

www.jestjs.cn/docs/gettin…

npm install --save-dev jest
目录
相关文章
|
3月前
|
JavaScript 前端开发 API
探索后端技术:Node.js的优势和实际应用
【10月更文挑战第6天】 在当今数字化时代,后端开发是任何成功软件应用的关键组成部分。本文将深入探讨一种流行的后端技术——Node.js,通过分析其核心优势和实际应用案例,揭示其在现代软件开发中的重要性和潜力。
236 2
|
2月前
|
监控 JavaScript 算法
如何使用内存监控工具来定位和解决Node.js应用中的性能问题?
总之,利用内存监控工具结合代码分析和业务理解,能够逐步定位和解决 Node.js 应用中的性能问题,提高应用的运行效率和稳定性。需要耐心和细致地进行排查和优化,不断提升应用的性能表现。
206 77
|
2月前
|
存储 缓存 JavaScript
如何优化Node.js应用的内存使用以提高性能?
通过以上多种方法的综合运用,可以有效地优化 Node.js 应用的内存使用,提高性能,提升用户体验。同时,不断关注内存管理的最新技术和最佳实践,持续改进应用的性能表现。
152 62
|
2月前
|
存储 缓存 监控
如何使用内存监控工具来优化 Node.js 应用的性能
需要注意的是,不同的内存监控工具可能具有不同的功能和特点,在使用时需要根据具体工具的要求和操作指南进行正确使用和分析。
84 31
|
2月前
|
JavaScript 前端开发 API
深入理解Node.js事件循环及其在后端开发中的应用
本文旨在揭示Node.js的核心特性之一——事件循环,并探讨其对后端开发实践的深远影响。通过剖析事件循环的工作原理和关键组件,我们不仅能够更好地理解Node.js的非阻塞I/O模型,还能学会如何优化我们的后端应用以提高性能和响应能力。文章将结合实例分析事件循环在处理大量并发请求时的优势,以及如何避免常见的编程陷阱,从而为读者提供从理论到实践的全面指导。
|
2月前
|
JavaScript
如何使用内存快照分析工具来分析Node.js应用的内存问题?
需要注意的是,不同的内存快照分析工具可能具有不同的功能和操作方式,在使用时需要根据具体工具的说明和特点进行灵活运用。
63 3
|
2月前
|
Web App开发 JSON JavaScript
Node.js 中的中间件机制与 Express 应用
Node.js 中的中间件机制与 Express 应用
|
4月前
|
JavaScript 开发者
深入理解Node.js事件循环及其在后端开发中的应用
【8月更文挑战第57天】本文将带你走进Node.js的事件循环机制,通过浅显易懂的语言和实例代码,揭示其背后的工作原理。我们将一起探索如何高效利用事件循环进行异步编程,提升后端应用的性能和响应速度。无论你是Node.js新手还是有一定经验的开发者,这篇文章都能给你带来新的启发和思考。
|
3月前
|
运维 JavaScript Linux
容器内的Nodejs应用如何获取宿主机的基础信息-系统、内存、cpu、启动时间,以及一个df -h的坑
本文介绍了如何在Docker容器内的Node.js应用中获取宿主机的基础信息,包括系统信息、内存使用情况、磁盘空间和启动时间等。核心思路是将宿主机的根目录挂载到容器,但需注意权限和安全问题。文章还提到了使用`df -P`替代`df -h`以获得一致性输出,避免解析错误。
101 0
|
3月前
|
JavaScript NoSQL 前端开发
使用 Node.js 和 MongoDB 构建实时聊天应用
【10月更文挑战第2天】使用 Node.js 和 MongoDB 构建实时聊天应用

热门文章

最新文章