前端用命令行交互

像一些前端的腳手架,比如 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ù)是否為必填,有默認值,和一下參數(shù)的提示,參數(shù)類型為什么等等

我們使用 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 支持定義多個子命令,我們可能會寫多個命令在一個文件,可以通過子命令來實現(xiàn)

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

第一個參數(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', // 默認值
            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', // 默認值
            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ù),但是有時候我們需要和 輸入的用戶進行交互,比如用命令 行生成一個項目,我們需要用戶來輸入項目名稱,或者項目的存放路徑。這時候如果讓用戶直接拼在一條命令行中, 是很不友好的。

Inquirer.js

參數(shù) 含義
type 提問的類型
name 存儲當前問題回答的變量
message 問題的描述
default 默認值
choices 列表選項
validate 對用戶的回答進行校驗
filter 對用戶的回答進行過濾處理,返回處理后的值
transformer 對用戶回答的顯示效果進行處理
when 根據(jù)前面問題的回答,判斷當前問題是否需要被回答
pageSize 渲染行數(shù)
prefix 修改message默認前綴
suffix 修改message默認后綴

還是繼續(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: "是否進行文件過濾?",
    name: "filter",
    suffix: "后綴",
    when: function(answers) { // 當watch為true的時候才會提問當前問題
        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è)置默認選項

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

對輸入值進行處理和校驗

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)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容