像一些前端的脚手架,比如 vue-cli 一样,直接在命令行输入一段命令就可以生成一个项目。这是怎么做到的呢?
yargs
我们用 yargs 来接受命令行的参数
先安装 yargs
npm install --save yargs
之后我们新建一个 hello.js
var argv = require('yargs').argv
console.log(argv)
之后我们在命令行中执行这个 js,$ node hello 1
就可以看到打印出 { _: [ 1 ], '$0': 'hello' }
我们在命令行带的参数都在 argv 的_属性中,以数组的形式,该属性可以获取非连词线开头的参数
但是我们如果传入的参数多了,这种保存在数组的形式肯定就没法满足我们的需求了。
在命令行中输入node hello --nama a
打印出来是{ _: [], nama: 'a', '$0': 'hello' }
这时我们可以看到参数可以以 key 和 value 的形式传入。我们只需以--key value
以形式输入即可。这样就使得我们的命令行传参有了很大的灵活性
除了--key value
外,还可以通过--key=value
形式传入
alias(别名)
有时候我们需要输入很多的参数时,会出现这种情况node hello --nama a --age 13 --sex man
,过多的 value 和 key,使得可能输入会比较繁琐。我们可以使用 alias 将需要的参数 key 起一个别名
let argv = require('yargs')
.alias('n', 'name')
.alias('a', 'age')
.alias('s', 'sex').argv
console.log(argv)
$ node hello -n dog -a 14 -s man
结果为:
{ _: [],
n: 'dog',
name: 'dog',
a: 14,
age: 14,
s: 'man',
sex: 'man',
'$0': 'hello' }
有时我们需要对一些参数有特殊要求,比如一些参数是否为必填,有默认值,和一下参数的提示,参数类型为什么等等
我们使用 option 方法,将所有这些配置写进一个对象
let argv = require('yargs').option('n', {
alias: 'name', // 别名
demand: true, // 是否必填
default: 'tom', // 默认值
describe: 'your name', // 对字段的描述
type: 'string' // 类型
}).argv
console.log(argv)
yargs 模块提供了一些方法,用于生成帮助信息,可以通过--help 来查看
let argv = require('yargs')
.option('n', {
alias: 'name', // 别名
demand: true, // 是否必填
default: 'tom', // 默认值
describe: 'your name', // 对字段的描述
type: 'string' // 类型
})
.usage('Usage: hello [options]') // 用法格式
.example('hello -n tom') //例子
.help('h') // 帮助信息
.epilog('it s my yargs').argv
console.log(argv)
$ node hello -h
Usage: hello [options]
选项:
--version 显示版本号 [布尔]
-n, --name your name [字符串] [必需] [默认值: "tom"]
-h 显示帮助信息 [布尔]
示例:
hello -n tom
it s my yargs
子命令 command
yargs 支持定义多个子命令,我们可能会写多个命令在一个文件,可以通过子命令来实现
require('yargs').command(
'way1',
'it is first way',
function(yargs) {
yargs.option('n', {
alias: 'name', // 别名
demand: true, // 是否必填
default: 'tom', // 默认值
describe: 'your name', // 对字段的描述
type: 'string' // 类型
})
},
function(argv) {
console.log(argv)
}
).argv
第一个参数为子命令的名称,第二个参数为命令描述,第三个为 yargs 的配置函数,第四个为处理接受到的参数函数
$ node hello way1 12 3 -n test
{ _: [ 'way1', 12, 3 ], n: 'test', name: 'test', '$0': 'hello' }
也可以通过以下方式,直接 接受子命令的参数
require('yargs').command(
'way1 <source> [proxy]',
'it is first way',
function(yargs) {
yargs.option('n', {
alias: 'name', // 别名
demand: true, // 是否必填
default: 'tom', // 默认值
describe: 'your name', // 对字段的描述
type: 'string' // 类型
})
},
function(argv) {
console.log(argv)
}
).argv
// <source> 表示source参数为必填, [proxy] 不是proxy选填
$ node hello way1 1 2 -n test
{ _: [ 'way1' ],
n: 'test',
name: 'test',
'$0': 'hello',
source: 1,
proxy: 2 }
如果有太多子命令,也可以通过模块化式来写 yargs
require('yargs').command(require('my-module')).argv
my-module.js
module.exports = {
command: 'way2',
describe: 'it is way2',
builder: function(yargs) {
yargs.option('n', {
alias: 'name', // 别名
demand: true, // 是否必填
default: 'tom', // 默认值
describe: 'your name', // 对字段的描述
type: 'string' // 类型
})
},
handler: function(argv) {
console.log(argv)
}
}
$ node hello way2 --name test2
{ _: [ 'way2' ], name: 'test2', n: 'test2', '$0': 'hello' }
yargs 是接受命令行的参数,但是有时候我们需要和 输入的用户进行交互,比如用命令 行生成一个项目,我们需要用户来输入项目名称,或者项目的存放路径。这时候如果让用户直接拼在一条命令行中, 是很不友好的。
Inquirer.js
参数 | 含义 |
---|---|
type | 提问的类型 |
name | 存储当前问题回答的变量 |
message | 问题的描述 |
default | 默认值 |
choices | 列表选项 |
validate | 对用户的回答进行校验 |
filter | 对用户的回答进行过滤处理,返回处理后的值 |
transformer | 对用户回答的显示效果进行处理 |
when | 根据前面问题的回答,判断当前问题是否需要被回答 |
pageSize | 渲染行数 |
prefix | 修改message默认前缀 |
suffix | 修改message默认后缀 |
还是继续写在我们的hello.js中
首先安装inquirer
npm install inquirer
const inquirer = require('inquirer');
const promptList = [
// {
// type: 'input',
// name: 'name'
// }
// 具体交互内容
];
inquirer.prompt(promptList).then(answers => {
console.log(answers); // 返回的结果
})
type 有 input, confirm, list, rawlist, expand, checkbox, password, editor这些类型
input 用户输入
const inquirer = require('inquirer');
const promptList = [
{
type: 'input',
name: 'name'
}
];
inquirer.prompt(promptList).then(answers => {
console.log(answers);
})
confirm 期望用户输入的Boolean,一般可以when一起使用,作为是否就行下一步
const inquirer = require('inquirer');
const promptList = [{
type: "confirm",
message: "是否使用监听?",
name: "watch",
prefix: "前缀"
},{
type: "confirm",
message: "是否进行文件过滤?",
name: "filter",
suffix: "后缀",
when: function(answers) { // 当watch为true的时候才会提问当前问题
return answers.watch
}
}]
inquirer.prompt(promptList).then(answers => {
console.log(answers);
})
list 列出可供用户选择的选项,和choices一起使用
const inquirer = require('inquirer');
const promptList = [{
type: 'list',
message: '请选择一种水果:',
name: 'fruit',
choices: [
"Apple",
"Pear",
"Banana"
]
}]
inquirer.prompt(promptList).then(answers => {
console.log(answers);
})
rawlist 带序号的选项,用户可通过输入序号来直接选择
const inquirer = require('inquirer');
const promptList = [{
type: 'rawlist',
message: '请选择一种水果:',
name: 'fruit',
choices: [
"Apple",
"Pear",
"Banana"
]
}]
inquirer.prompt(promptList).then(answers => {
console.log(answers);
})
expand 可联想的选项
const inquirer = require('inquirer');
const promptList = [{
type: "expand",
message: "请选择一种水果:",
name: "fruit",
choices: [
{
key: "a", // 联想的关键词 必填
name: "Apple", // 联想显示出来的值 非必填, 如果没有写,联想出来的值为value值
value: "apple" // 选中后的值 非必填, 如果没有写,选中后的值为name值
},
{
key: "p",
name: "Pear",
value: "pear"
}
]
}]
inquirer.prompt(promptList).then(answers => {
console.log(answers);
})
checkbox 单选 可以设置默认选项
const promptList = [{
type: "checkbox",
message: "选择颜色:",
name: "color",
choices: [
{
name: "red"
},
{
name: "blur",
checked: true // 默认选中
},
{
name: "green"
},
{
name: "yellow"
}
]
}];
// 或者下面这样
const promptList = [{
type: "checkbox",
message: "选择颜色:",
name: "color",
choices: [
"red",
"blur",
"green",
"yellow"
]
}];
password 密码类型
const inquirer = require('inquirer');
const promptList = [{
type: "password", // 密码为密文输入
message: "请输入密码:",
name: "pwd"
}];
inquirer.prompt(promptList).then(answers => {
console.log(answers);
})
除了上面列举的这些方法外,还可以通过new inquirer.Separator()
添加分隔符,pageSize
来设置选项展示行数
const inquirer = require('inquirer');
const promptList = [{
type: 'rawlist',
message: '请选择一种水果:',
name: 'fruit',
choices: [
"Apple",
new inquirer.Separator("--- 分隔符 ---"), // 自定义分隔符
"Pear",
new inquirer.Separator(), // 分隔符
"Banana"
],
pageSize: 2 // 只展示两行
}]
inquirer.prompt(promptList).then(answers => {
console.log(answers);
})
对输入值进行处理和校验
const inquirer = require('inquirer');
const promptList = [{
type: "input",
message: "请输入十一位数字",
name: "num",
validate: function(val) {
return /^\d{11}$/.test(val)
// val 为用户输入的值,return true会继续下去,return false则会停在该步骤
}
}];
inquirer.prompt(promptList).then(answers => {
console.log(answers);
})
注意:filter会比validate先执行
const inquirer = require('inquirer');
const promptList = [{
type: "input",
message: "请输入十一位数字",
name: "num",
filter: function(val) {
return '0086' + val
},
validate: function(val) {
return /^\d{11}$/.test(val)
}];
inquirer.prompt(promptList).then(answers => {
console.log(answers);
})
这里如果输入11位数字,是没法继续下去的, 只有输入7位数字才可以。filter和validate的先后顺序没有关系