像一些前端的腳手架赡矢,比如 vue-cli 一樣,直接在命令行輸入一段命令就可以生成一個項目。這是怎么做到的呢扔仓?
yargs
我們用 yargs 來接受命令行的參數(shù)
先安裝 yargs
npm install --save yargs
之后我們新建一個 hello.js
var argv = require('yargs').argv
console.log(argv)
之后我們在命令行中執(zhí)行這個 js播玖,$ node hello 1
就可以看到打印出 { _: [ 1 ], '$0': 'hello' }
我們在命令行帶的參數(shù)都在 argv 的_屬性中椎工,以數(shù)組的形式,該屬性可以獲取非連詞線開頭的參數(shù)
但是我們?nèi)绻麄魅氲膮?shù)多了蜀踏,這種保存在數(shù)組的形式肯定就沒法滿足我們的需求了维蒙。
在命令行中輸入node hello --nama a
打印出來是{ _: [], nama: 'a', '$0': 'hello' }
這時我們可以看到參數(shù)可以以 key 和 value 的形式傳入。我們只需以--key value
以形式輸入即可果覆。這樣就使得我們的命令行傳參有了很大的靈活性
除了--key value
外颅痊,還可以通過--key=value
形式傳入
alias(別名)
有時候我們需要輸入很多的參數(shù)時,會出現(xiàn)這種情況node hello --nama a --age 13 --sex man
,過多的 value 和 key局待,使得可能輸入會比較繁瑣斑响。我們可以使用 alias 將需要的參數(shù) 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
結(jié)果為:
{ _: [],
n: 'dog',
name: 'dog',
a: 14,
age: 14,
s: 'man',
sex: 'man',
'$0': 'hello' }
有時我們需要對一些參數(shù)有特殊要求菱属,比如一些參數(shù)是否為必填,有默認(rèn)值舰罚,和一下參數(shù)的提示纽门,參數(shù)類型為什么等等
我們使用 option 方法,將所有這些配置寫進(jìn)一個對象
let argv = require('yargs').option('n', {
alias: 'name', // 別名
demand: true, // 是否必填
default: 'tom', // 默認(rèn)值
describe: 'your name', // 對字段的描述
type: 'string' // 類型
}).argv
console.log(argv)
yargs 模塊提供了一些方法营罢,用于生成幫助信息赏陵,可以通過--help 來查看
let argv = require('yargs')
.option('n', {
alias: 'name', // 別名
demand: true, // 是否必填
default: 'tom', // 默認(rèn)值
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 [字符串] [必需] [默認(rèn)值: "tom"]
-h 顯示幫助信息 [布爾]
示例:
hello -n tom
it s my yargs
子命令 command
yargs 支持定義多個子命令,我們可能會寫多個命令在一個文件饲漾,可以通過子命令來實現(xiàn)
require('yargs').command(
'way1',
'it is first way',
function(yargs) {
yargs.option('n', {
alias: 'name', // 別名
demand: true, // 是否必填
default: 'tom', // 默認(rèn)值
describe: 'your name', // 對字段的描述
type: 'string' // 類型
})
},
function(argv) {
console.log(argv)
}
).argv
第一個參數(shù)為子命令的名稱蝙搔,第二個參數(shù)為命令描述,第三個為 yargs 的配置函數(shù)能颁,第四個為處理接受到的參數(shù)函數(shù)
$ node hello way1 12 3 -n test
{ _: [ 'way1', 12, 3 ], n: 'test', name: 'test', '$0': 'hello' }
也可以通過以下方式杂瘸,直接 接受子命令的參數(shù)
require('yargs').command(
'way1 <source> [proxy]',
'it is first way',
function(yargs) {
yargs.option('n', {
alias: 'name', // 別名
demand: true, // 是否必填
default: 'tom', // 默認(rèn)值
describe: 'your name', // 對字段的描述
type: 'string' // 類型
})
},
function(argv) {
console.log(argv)
}
).argv
// <source> 表示source參數(shù)為必填, [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', // 默認(rèn)值
describe: 'your name', // 對字段的描述
type: 'string' // 類型
})
},
handler: function(argv) {
console.log(argv)
}
}
$ node hello way2 --name test2
{ _: [ 'way2' ], name: 'test2', n: 'test2', '$0': 'hello' }
yargs 是接受命令行的參數(shù)败玉,但是有時候我們需要和 輸入的用戶進(jìn)行交互,比如用命令 行生成一個項目镜硕,我們需要用戶來輸入項目名稱运翼,或者項目的存放路徑。這時候如果讓用戶直接拼在一條命令行中兴枯, 是很不友好的血淌。
Inquirer.js
參數(shù) | 含義 |
---|---|
type | 提問的類型 |
name | 存儲當(dāng)前問題回答的變量 |
message | 問題的描述 |
default | 默認(rèn)值 |
choices | 列表選項 |
validate | 對用戶的回答進(jìn)行校驗 |
filter | 對用戶的回答進(jìn)行過濾處理,返回處理后的值 |
transformer | 對用戶回答的顯示效果進(jìn)行處理 |
when | 根據(jù)前面問題的回答财剖,判斷當(dāng)前問題是否需要被回答 |
pageSize | 渲染行數(shù) |
prefix | 修改message默認(rèn)前綴 |
suffix | 修改message默認(rèn)后綴 |
還是繼續(xù)寫在我們的hello.js中
首先安裝inquirer
npm install inquirer
const inquirer = require('inquirer');
const promptList = [
// {
// type: 'input',
// name: 'name'
// }
// 具體交互內(nèi)容
];
inquirer.prompt(promptList).then(answers => {
console.log(answers); // 返回的結(jié)果
})
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: "是否使用監(jiān)聽躺坟?",
name: "watch",
prefix: "前綴"
},{
type: "confirm",
message: "是否進(jìn)行文件過濾沦补?",
name: "filter",
suffix: "后綴",
when: function(answers) { // 當(dāng)watch為true的時候才會提問當(dāng)前問題
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 可聯(lián)想的選項
const inquirer = require('inquirer');
const promptList = [{
type: "expand",
message: "請選擇一種水果:",
name: "fruit",
choices: [
{
key: "a", // 聯(lián)想的關(guān)鍵詞 必填
name: "Apple", // 聯(lián)想顯示出來的值 非必填咪橙, 如果沒有寫夕膀,聯(lián)想出來的值為value值
value: "apple" // 選中后的值 非必填, 如果沒有寫美侦,選中后的值為name值
},
{
key: "p",
name: "Pear",
value: "pear"
}
]
}]
inquirer.prompt(promptList).then(answers => {
console.log(answers);
})
checkbox 單選 可以設(shè)置默認(rèn)選項
const promptList = [{
type: "checkbox",
message: "選擇顏色:",
name: "color",
choices: [
{
name: "red"
},
{
name: "blur",
checked: true // 默認(rèn)選中
},
{
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
來設(shè)置選項展示行數(shù)
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);
})
對輸入值進(jìn)行處理和校驗
const inquirer = require('inquirer');
const promptList = [{
type: "input",
message: "請輸入十一位數(shù)字",
name: "num",
validate: function(val) {
return /^\d{11}$/.test(val)
// val 為用戶輸入的值菠剩,return true會繼續(xù)下去易猫,return false則會停在該步驟
}
}];
inquirer.prompt(promptList).then(answers => {
console.log(answers);
})
注意:filter會比validate先執(zhí)行
const inquirer = require('inquirer');
const promptList = [{
type: "input",
message: "請輸入十一位數(shù)字",
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位數(shù)字,是沒法繼續(xù)下去的具壮, 只有輸入7位數(shù)字才可以擦囊。filter和validate的先后順序沒有關(guān)系