node.js命令行教程图文详解


Posted in Javascript onMay 27, 2019

本文先介绍原生的node.js实现命令行交互,了解原生的api,然后通过commander.js和inquirer.js实现一个完整的交互命令行工具。

项目地址

process (进程)

process对象是一个全局变量,它提供了当前node.js进程的信息并对其控制。因为其是一个全局变量所以无需在文件中引入。

需要用到的几个api

  • process.argv
  • process.cwd()
  • process.stdin
  • process.stdout
  • process.stdin.resume()
  • process.argv

process.argv

属性返回一个数组。数组的第一个值是process.execPath,第二个是正在执行的JavaScript的文件路径,其余参数为其它命令参数,这是我们来自定义命令的关键。

示例

新建argv.js

// argv.js
console.log(process.argv)

执行node命令node argv.js

node argv.js --name zhu
## 输出
[ '/usr/local/bin/node', ## 执行当前脚本的Node二进制文件的绝对路径
 '/Users/zhuhuilong/Node/Book/argv.js', ## 文件的绝对路径
 '--name', ## 其余参数
 'zhu' ]

接收自定义的命令参数进行处理输出

// argv.js
console.log(process.argv)

let argvs = process.argv

let param = argvs.splice(2)
if(param[0] && param[0] == '--name'){
 if(param[1]){
 console.log(`hello ${param[1]}`)
 }else{
 console.log('请输入name')
 }
}

运行argv.js

node argv.js --name zhu
## 输出
[ '/usr/local/bin/node',
 '/Users/zhuhuilong/Node/Book/argv.js',
 '--name',
 'zhu' ]
hello zhu
param [ '--name', 'zhu' ]

process.stdin与process.stdout

process.stdin(标准输入)

process.stdin 属性返回连接到 stdin (fd 0) 的流。 它是一个 net.Socket 流(也就是双工流),除非 fd 0 指向一个文件,在这种情况下它是一个可读流。

process.stdout(标准输出)

process.stdout 属性返回连接到 stdout (fd 1) 的流。 它是一个 net.Socket 流(也就是双工流),除非 fd 1 指向一个文件,在这种情况下它是一个可写流。

process.stdin.resume()

  • 一个指向 标准输入流(stdin) 的可读流(Readable Stream)。标准输入流默认是暂停 (pause) 的,所以必须要调用 process.stdin.resume() 来恢复 (resume) 接收。
  • 作为流,process.stdin可以在旧模式下使用。为了兼容node v0.10以前的版本。在旧模式喜爱使用stdin必须调用process.stdin.resume()。注意如果调用了process.stdin.resume() stdin将转为旧模式。

通俗来讲就是控制台等待我们输入内容不退出进程,对输入输出进行交互。

新建inputout.js

// inputout.js
process.stdin.setEncoding('utf8')

let argvs = process.argv

let param = argvs.splice(2)
if (param[0] && param[0] == '--name') {
 if (param[1]) {
 console.log(`hello ${param[1]}`)
 } else {
 process.stdout.write(`请输入name:`)
 process.stdin.resume()
 process.stdin.on('data', chunk => {
  if (!!chunk.replace(/[\r\n]/g, '')) {
  process.stdout.write(`你输入的name是: ${chunk}`)
  process.stdin.emit('end')
  } else {
  process.stdout.write(`请输入name:`)
  }
 })
 }
}

process.stdin.on('end', () => {
 process.stdout.write('结束\n')
})

>执行node inputout.js --name

node.js命令行教程图文详解

node.js命令行教程图文详解

备注

在新版本node模式下可以使用process.stdin.on("readable",()=>{})代替process.stdin.resume()恢复输入流接收。

示例:

process.stdin.on("readable", () => {
 var chunk = process.stdin.read();
 console.log(typeof(chunk))
 if (chunk !==null) {
 process.stdout.write(`data: ${chunk}`);
 process.stdin.emit("end");
 }
});

process.stdin.on("end", () => {
 process.stdout.write("end");
});

从上面的示例我们可以拿到process.argv参数对其进行处理交互,但如果要实现更复杂的命令交互,使用上面的方法会很吃力。下面我们使用commander.js和inquirer来实现一个完整的node命令行工具(创建项目模版)。

commander.js

node.js命令行界面的完整解决方案,受Ruby Commander启发。

commander.js的API简述

program.version() 声明版本

const program = require('commander')
const pkg = require('../package.json')
program.version(pkg.version)

Options 解析

使用.option()方法定义commander的选项options,也可以作为选项的文档。

var program = require('commander');
 
program
 .version('0.1.0')
 .option('-p, --peppers', 'Add peppers')
 .option('-P, --pineapple', 'Add pineapple')
 .option('-b, --bbq-sauce', 'Add bbq sauce')
 .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')
 .parse(process.argv);
 
console.log('you ordered a pizza with:');
if (program.peppers) console.log(' - peppers');
if (program.pineapple) console.log(' - pineapple');
if (program.bbqSauce) console.log(' - bbq');
console.log(' - %s cheese', program.cheese);

添加自定义命令program.command()

var program = require('commander');
 
program
 .command('rm <dir>') //<>必选参数,如果是[]则是可选参数
 .option('-r, --recursive', 'Remove recursively')
 .action(function (dir, cmd) {
 console.log('remove ' + dir + (cmd.recursive ? ' recursively' : ''))
 })
 
program.parse(process.argv)

// command()可变参数
/** 命令command有且只有最后一个参数可变不固定的。 要使参数变量可变,必须将...附加到参数名称。**/
program
 .version('0.1.0')
 .command('rmdir <dir> [otherDirs...]')
 .action(function (dir, otherDirs) {
 console.log('rmdir %s', dir);
 if (otherDirs) {
  otherDirs.forEach(function (oDir) {
  console.log('rmdir %s', oDir);
  });
 }
 });
program.parse(process.argv);

program.action() 定义命令的回调函数

var program = require("commander");

program
 .command("rm <dir>")
 .option("-r, --recursive", "Remove recursively")
 .option("-f, --force", "remove force")
 .action(function(dir, cmd) {
 // cmd为option参数选项
 //console.log('cmd',cmd)
 if (cmd.recursive) {
  console.log("remove " + dir + " recursively");
 }
 if (cmd.force) {
  console.log("remove " + dir + " forcefully");
 }
 });

program.parse(process.argv);

inquirer.js

Inquirer.js 使用NodeJs做的一个通用交互式命令行用户界面的集合。具有常用的控制台交互操作。

node.js命令行教程图文详解

由于交互的问题种类不同,inquirer为每个问题提供很多参数:

  • type:表示提问的类型,包括:input, confirm, list, rawlist, expand, checkbox, password, editor;
  • name: 存储当前问题回答的变量;
  • message:问题的描述;
  • default:默认值;
  • choices:列表选项,在某些type下可用,并且包含一个分隔符(separator);
  • validate:对用户的回答进行校验;
  • filter:对用户的回答进行过滤处理,返回处理后的值;
  • transformer:对用户回答的显示效果进行处理(如:修改回答的字体或背景颜色),但不会影响最终的答案的内容;
  • when:根据前面问题的回答,判断当前问题是否需要被回答;
  • pageSize:修改某些type类型下的渲染行数;
  • prefix:修改message默认前缀;
  • suffix:修改message默认后缀。
  • 创建cli.js
const program = require('commander')
const inquirer = require('inquirer')
const fs = require('fs')
const path = require('path')
const pkg = require('../package.json')

const CWD = process.cwd()

const promptList = [
 {
 type: 'list',
 message: '请选择一种模版',
 name: 'template',
 choices: ['vue', 'angular', 'webpack-m-pages'],
 filter: function(val) {
  return val.toLowerCase()
 }
 }
]

program
 .version(pkg.version)
 .command('create <dir>')
 .description('create project template')
 .action(function(dir, cmd) {
 const TEMPLATE_PATH = path.join(CWD, dir)
 if (fs.existsSync(TEMPLATE_PATH)) {
 } else {
  fs.mkdirSync(TEMPLATE_PATH)
 }
 if (dir) {
  inquirer.prompt(promptList).then(anwsers => {
  console.log(anwsers)
  })
 }
 })

program.parse(process.argv)

运行 node cli/cli.js create vue

node.js命令行教程图文详解

已经可以运行了,我们自定义一个命名替代每次都执行node

命令为:test-cli create <dir>

1、创建bin文件夹,在bin文件夹下创建index.js文件

#!/usr/bin/env node

require('../cli/cli')

2、修改package.json文件

添加bin选项

"bin": {
 "test-cli": "./bin/index.js"
 },

3、执行npm link (如果没有权限,执行sudo npm link)

4、测试

node.js命令行教程图文详解

5、发布 npm publish (如果未登录需先 npm login登录)

6、发布完毕,需npm unlink解除本地的命令映射

npm install -g XXX

总结

以上所述是小编给大家介绍的node.js命令行教程图文详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
Mootools 1.2教程 同时进行多个形变动画
Sep 15 Javascript
js同比例缩放图片的小例子
Oct 30 Javascript
jQuery时间轴插件使用详解
Jul 16 Javascript
jQuery与getJson结合的用法实例
Aug 07 Javascript
jQuery学习笔记之Ajax用法实例详解
Dec 01 Javascript
js判断复选框是否选中及选中个数的实现代码
May 30 Javascript
详解用原生JavaScript实现jQuery的某些简单功能
Dec 19 Javascript
js实现自定义进度条效果
Mar 15 Javascript
jQuery插件FusionCharts绘制的2D双面积图效果示例【附demo源码】
Apr 11 jQuery
详解搭建一个vue-cli的移动端H5开发模板
Jan 17 Javascript
Vue+webpack实现懒加载过程解析
Feb 17 Javascript
vue 监听 Treeselect 选择项的改变操作
Aug 31 Javascript
详解JavaScript中的坐标和距离
May 27 #Javascript
优化Vue项目编译文件大小的方法步骤
May 27 #Javascript
了解JavaScript表单操作和表单域
May 27 #Javascript
分享一个vue项目“脚手架”项目的实现步骤
May 26 #Javascript
使用JS判断页面是首次被加载还是刷新
May 26 #Javascript
Node.js 多进程处理CPU密集任务的实现
May 26 #Javascript
小程序封装路由文件和路由方法(5种全解析)
May 26 #Javascript
You might like
phpMyAdmin 安装及问题总结
2009/05/28 PHP
php数组函数序列之array_keys() - 获取数组键名
2011/10/30 PHP
PHP输出时间差函数代码
2013/01/28 PHP
smarty模板引擎之配置文件数据和保留数据
2015/03/30 PHP
PHP实现基于状态的责任链审批模式详解
2019/05/31 PHP
PHP基于session.upload_progress 实现文件上传进度显示功能详解
2019/08/09 PHP
定义select的边框颜色
2008/04/28 Javascript
简单实现jQuery进度条轮播实例代码
2016/06/20 Javascript
基于 Vue.js 2.0 酷炫自适应背景视频登录页面实现方式
2018/01/17 Javascript
JS和Canvas实现图片的预览压缩和上传功能
2018/03/30 Javascript
vue写一个组件
2018/04/09 Javascript
微信小程序实现图片翻转效果的实例代码
2019/09/20 Javascript
jquery轻量级数字动画插件countUp.js使用详解
2019/10/17 jQuery
Flexible.js可伸缩布局实现方法详解
2020/11/13 Javascript
[06:36]吞吞映像top1
2014/06/20 DOTA
[00:57]辉夜杯战队访谈宣传片—VG
2015/12/25 DOTA
[01:22]DOTA2神秘商店携大量周边降临完美大师赛
2017/11/07 DOTA
[01:38]2018DOTA2亚洲邀请赛主赛事第二日现场采访 神秘商人痛陈生计不易
2018/04/05 DOTA
python k-近邻算法实例分享
2014/06/11 Python
使用python检测主机存活端口及检查存活主机
2015/10/12 Python
Python 模拟员工信息数据库操作的实例
2017/10/23 Python
python中in在list和dict中查找效率的对比分析
2018/05/04 Python
python的格式化输出(format,%)实例详解
2018/06/01 Python
Python企业编码生成系统总体系统设计概述
2019/07/26 Python
python PIL和CV对 图片的读取,显示,裁剪,保存实现方法
2019/08/07 Python
Python求正态分布曲线下面积实例
2019/11/20 Python
python代码如何实现余弦相似性计算
2020/02/09 Python
使用python-pptx包批量修改ppt格式的实现
2020/02/14 Python
css3实现一个div设置多张背景图片及background-image属性实例演示
2017/08/10 HTML / CSS
美国户外生活方式品牌:Eddie Bauer
2016/12/28 全球购物
给水排水工程专业毕业生推荐信
2013/10/28 职场文书
数控专业自荐书范文
2014/03/16 职场文书
村党支部换届选举方案
2014/05/02 职场文书
团支部推优材料
2014/05/21 职场文书
离婚协议书格式范本
2016/03/18 职场文书
在pycharm中无法import所安装的库解决方案
2021/05/31 Python