持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情
Node.js 有很多竞争者。一段时间以来最知名的竞争对手是 Deno。但是,不要误以为 Node.js 已经过时。它一直存在很多问题和争议,但时至今日,它仍然是一个不错的选择。
Deno 仍有很多工作要做。它最初的炒作似乎已经降温。Node.js 的生态系统非常庞大,Deno 的成熟和使用还需要一点时间。
在本文中,我想通过创建命令行交互式用户界面来简单的举例说明 Node.js 生态系统的丰富性。通过使用Inquirer.js
来创建漂亮的命令行交互。 您可能已经用过它,其中Remix
或NextJs
正在使用Inquirer.js
。
安装
它是一个npm
依赖项,因此只需执行以下操作即可轻松安装:
$ npm install --save inquirer
尽管commonjs
模块多年来一直是 node 的首选,但v9
版本和更高版本都是基于本地esm
模块构建的。Node从 v12
版本 开始就支持esm
模块。
如果您需要它在较旧的Node版本上运行,则必须安装它的最新v8
版本。
*// will install the latest 8 versions*\
npm install --save inquirer@^8.0.0
开始使用该库所需要做的就是简单地导入它。这是执行此操作的代码:
// v8 and lower
const inquirer = require('inquirer');
// v9 an higher
import inquirer from 'inquirer';
Prompts
Prompts API
非常直观的围绕着Promises
,这使得它非常易于使用和推理。或者,我们也可以使用他们的文档Rx.Observales
中提到的React Interface
。在本文中,我们将重点介绍基于 Promise 的接口。
我们将某些内容打印到屏幕上的方式非常简单:
inquirer.prompt(questions) -> promise
对于复杂的用例,可以使用inquirer.registerPrompt
和inquirer.createPrompModule
.
Questions —— 问题
inquirer.prompt
可以定义向用户提出的问题的方式。
由于交互的问题种类不同,inquirer为每个问题提供很多参数,举例如下几种:
validate
: 接收用户输入并返回true
或false
。也可以通过使用this.async()
方法来实现异步。filter
:过滤用户输入的方法。transform
:一种转换用户输入的方法。default
: 值或函数返回问题的默认值。如果用户输入enter,它将默认为这个。when
:有条件地隐藏/显示问题的功能。
最重要key
的是哪个类型。如果省略,它将默认为input
. 让我们看看我们可以使用的不同类型:
1.input
这只是最基本的一个类型。代码如下:
import inquirer from 'inquirer';
inquirer.prompt([
{
type: 'input',
name: 'favColor',
message: 'What is your favorite color?',
default: 'Blue'
},
]).then(answers => {
console.info('Your answer are :', JSON.stringify(answers));
});
结果如下:
2.List
要使用该list
类型,我们需要设置type: 'list'
并提供一个choices
数组列表。我们可以disabled
使用分隔符显示选项并设置布局样式new inquirer.Separator
。
import inquirer from 'inquirer';
inquirer.prompt([
{
type: 'list',
name: 'contactSupport',
message: 'How do you want to contact support?',
choices: [
'By email',
'By phone',
{
name: 'By fax',
disabled: 'Not supported anymore',
},
new inquirer.Separator(),
'Have our agents call you',
],
},
]).then(answers => {
console.info('Your answer are :', JSON.stringify(answers));
});
结果如下:
3、rawlist
rawlist
不接受数组选项中有对象,只接受字符串。它让我们可以使用光标回复或直接输入选项编号。它将验证输入索引。
import inquirer from 'inquirer';
inquirer.prompt([
{
type: 'rawlist',
name: 'contactSupport',
message: 'How do you want to contact support?',
default: 'By phone',
choices: [
'By email',
'By phone',
'Have our agents call you',
],
},
]).then(answers => {
console.info('Your answer are :', JSON.stringify(answers));
});
结果如下:
4、expend
扩展类型与前一种类似,不同之处在于它将隐藏所有选项以减少冗长的界面。它将仅公开key
每个选择的绑定。默认选项为大写。
建议将默认选项保留为空白,因此如果用户键入 enter,将给他们显示选项列表。
import inquirer from 'inquirer';
inquirer.prompt([
{
type: 'expend',
name: 'support',
message: 'How do you want to contact support?',
default: 'email',
choices: [
{
key: 'e',
name: 'By email',
value: 'email'
},
{
key: 'p',
name: 'By phone',
value: 'phone'
},
{
key: 'a',
name: 'Have our agents call',
value: 'agent'
},
],
},
]).then(answers => {
console.info('Your answer are :', JSON.stringify(answers));
});
5.Checkbox
复选框的特殊性在于,要具有默认值,我们必须将其标记为check: true
选项数组。
import inquirer from 'inquirer';
inquirer.prompt([
{
type: 'checkbox',
name: 'support',
message: 'Select your contact support preferences?',
choices: [
{
name: 'By email'
},
{
name: 'By chat',
checked: false,
},
{
name: 'By pone',
checked: true,
},
{
name: 'Have our agents call',
},
],
},
]).then(answers => {
console.info('Your answer are :', JSON.stringify(answers));
});
结果如下:
6.Confirm
这是一种在许多项目中使用的常见模式。
import inquirer from 'inquirer';
inquirer.prompt([
{
type: 'confirm',
name: 'contactByEmail',
message: 'Do you want to be contacted by email',
defalut: false
},
]).then(answers => {
console.info('Your answer are :', JSON.stringify(answers));
});
结果如下:
7.Editor
编辑器将启动默认终端编辑器以获得更舒适的输入。
import inquirer from 'inquirer';
inquirer.prompt([
{
type: 'editor',
name: 'support',
message: 'Please write your support query.',
waitUserInput: true
},
]).then(answers => {
console.info('Your answer are :', JSON.stringify(answers));
});
结果如下:
8.Password
还有一种输入敏感数据的类型。这将完全隐藏输入(如输入 sudo 密码时)或用我们喜欢的字符屏蔽输入。
import inquirer from 'inquirer';
const requireLetterAndNumber = (value) => {
if (/\w/.test(value) && /\d/.test(value)) {
return true;
}
return 'Password need to have at least a letter and a number';
};
inquirer.prompt([
{
type: 'Password',
message: 'Enter a masked password',
name: 'password2',
mask: '*',
validate: requireLetterAndNumber,
},
]).then(answers => {
console.info('Your answer are :', JSON.stringify(answers));
});
结果如下:
\
问题关联
在某些情况下,您可能希望根据以前的答案包含或删除问题。有两种方法可以解决:
-
when
:方法返回true时显示问题,false时隐藏问题。 - 嵌套提示:将 promise 的结果与之前的答案嵌套在另一个提示中。
when
import inquirer from 'inquirer'; | inquirer.prompt([
{
type: 'confirm',
name: 'pizzaFav',
message: 'Is pizza your favorite food?'
},
{
type: 'input',
name: 'why',
message: 'Oh! What could be more delicious than pizza?'
when: (answers) => answers.pizzaFav === false
},
]).then(answers => {
console.info('Your answer are :', JSON.stringify(answers));
});
嵌套提示
import inquirer from 'inquirer';
inquirer.prompt([
{
type: 'confirm',
name: 'pizzaFav',
message: 'Is pizza your favorite food?'
}
]).then(answers => {
if(!answers.pizzaFav) {
inquirer.prompt({
type: 'input',
name: 'why',
message: 'Oh! What could be more delicious than pizza?',
});
}
});
上面的代码片段产生相同的结果:
总结:
该Inquirer
库使 Node.js 中任何基于设置过程的设置过程变得有趣和简单。它为我们想要显示的内容提供了很多控制和粒度。有很多自定义,代码干净易读。
创建一个引人入胜且简单的设置过程可能是成功的关键。Inquirer
承担了我们所有的繁重工作,因此我们可以专注于真正重要的事情!