前端用命令行交互

像一些前端的腳手架赡矢,比如 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);
})

WX20181228-201642@2x.png

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);
})
WX20181228-202422@2x.png

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);
})

![WX20181228-203132@2x.png](https://upload-images.jianshu.io/upload_images/14717762-a4d2d7e42b3307be.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

rawlist 帶序號的選項,用戶可通過輸入序號來直接選擇

const inquirer = require('inquirer');

const promptList = [{
  type: 'rawlist',
  message: '請選擇一種水果:',
  name: 'fruit',
  choices: [
      "Apple",
      "Pear",
      "Banana"
  ]
}]

inquirer.prompt(promptList).then(answers => {
    console.log(answers);
})

WX20181228-203132@2x.png

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);
})
WX20181228-204034@2x.png

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"
    ]
}];
WX20181228-204506@2x.png

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)系

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末违霞,一起剝皮案震驚了整個濱河市嘴办,隨后出現(xiàn)的幾起案子瞬场,更是在濱河造成了極大的恐慌,老刑警劉巖涧郊,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贯被,死亡現(xiàn)場離奇詭異,居然都是意外死亡妆艘,警方通過查閱死者的電腦和手機彤灶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來批旺,“玉大人幌陕,你說我怎么就攤上這事∑螅” “怎么了搏熄?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長暇赤。 經(jīng)常有香客問我心例,道長,這世上最難降的妖魔是什么鞋囊? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任止后,我火速辦了婚禮,結(jié)果婚禮上溜腐,老公的妹妹穿的比我還像新娘译株。我一直安慰自己,他們只是感情好挺益,可當(dāng)我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布歉糜。 她就那樣靜靜地躺著,像睡著了一般矩肩。 火紅的嫁衣襯著肌膚如雪现恼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天黍檩,我揣著相機與錄音叉袍,去河邊找鬼。 笑死刽酱,一個胖子當(dāng)著我的面吹牛喳逛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播棵里,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼润文,長吁一口氣:“原來是場噩夢啊……” “哼姐呐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起典蝌,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤曙砂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后骏掀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鸠澈,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年截驮,在試婚紗的時候發(fā)現(xiàn)自己被綠了笑陈。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡葵袭,死狀恐怖涵妥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情坡锡,我是刑警寧澤蓬网,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站娜氏,受9級特大地震影響拳缠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贸弥,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一窟坐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧绵疲,春花似錦哲鸳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至郁岩,卻和暖如春婿奔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背问慎。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工萍摊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人如叼。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓冰木,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子踊沸,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內(nèi)容

  • Node.js是目前非承眨火熱的技術(shù),但是它的誕生經(jīng)歷卻很奇特逼龟。 眾所周知评凝,在Netscape設(shè)計出JavaScri...
    w_zhuan閱讀 3,617評論 2 41
  • 第一章:編譯和安裝SCons第二章:簡單編譯第三章:編譯相關(guān)的一些事情第四章:編譯和鏈接庫文件第五章:節(jié)點對象第六...
    仙靈兒閱讀 11,839評論 0 3
  • 最近睡眠一直不好,已經(jīng)持續(xù)一段時間了审轮,晚上經(jīng)常多夢肥哎,多數(shù)是一直處于夢中,導(dǎo)致睡眠質(zhì)量不高疾渣,白天氣色不好,身體疲憊...
    星期八_靜閱讀 298評論 2 1
  • 001 最近忙于年終總結(jié)崖飘,學(xué)習(xí)進(jìn)度拖后了榴捡,英語流利說一直沒有晉級,要加快進(jìn)度了朱浴,學(xué)習(xí)之前先復(fù)習(xí)單詞吊圾。 002 逐字...
    愛晴海的陽光閱讀 227評論 0 0
  • 漸行漸遠(yuǎn)的記憶(一) 那時候的房子都很矮,站在我家的土墻頭上就能看見全村的房子翰蠢,還有村頭的農(nóng)田…… 沒事的我常坐在...
    云在天上飄閱讀 481評論 0 0