【nodejs脚手架开发】交互处理-Inquirer.js篇
上一篇 文章讲解了nodejs开发的第一步,命令处理,命令处理的短板是无法处理复杂的选项,而inquier.js解决了这一问题。这篇文章继续介绍脚手架中的交互处理。
什么是交互?
说交互可能会引发一些歧义,我个人习惯将交互理解为客服,我们在购物的时候,客服会向你问一系列的问题,比如:
- 你的性别是?
- 你的身高是?
- 请您选一个衣服颜色(红,黄,白,绿, 黑)
- 体恤还是夹克?
- 。。。。
等等问题,然后会根据你的需求,向你推荐合适的衣服。而Inquirer.js在命令行开发中则承担了这一角色,让我们根据使用者的需要,来做相应的处理。比如vue-cli中的vue create命令,在创建项目时会问以下问题:
- 选择预设:Please pick a preset
- 选择特性:Check the features needed for your project
- 选择vue版本:Choose a version of Vue.js that you want to start the project with
- 选择css预处理器:Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default)
- 选择eslint校验时机:Pick additional lint features
- 。。。。
什么是Inquirer.js?
如图,inquirer.js主要包括问题的类型和问题的处理两个部分,问题的类型包含:
- input:可以理解为填空题,需要用户输入
- confirm: 由用户通过快捷键y/n选择是/否,判断题
- list: 无序列表单选题
- rawlist: 有序列表单选题
- expand: 可以通过key定义快捷选择,如A, B, C, D 选择题
- checkbox: 多选题
- pasword: 密码输入,输入时掩码代替显示
- editor: 通过vim编辑器输入
问题的处理比较简单也比较丰富,主要包括以下属性:
- message: 问题的描述
- name: 问题答案值的属性名,可以理解为form表单prop
- choices: 选项列表
- pagesize: choices过多时每页显示的个数
- surfix和prefix:问题描述的前后缀
- default: 默认值
- when: 问题回答后的回调函数,可以处理问题的依赖关系
- filter: 对回答进行过滤
- validate: 对回答进行验证
- transformer: 对回答进行格式化显示,但不会改变回答的值
讲了这么多概念,如果我们要做一个选择题,写法如下:
代码语言:txt复制const inquirer = require('inquirer')
const propmtList = [{
type: 'list',
message: 'Please pick a preset',
name: 'preset',
choices: [
"Default ([Vue 2] babel, eslint)",
"Default (Vue 3 Preview) ([Vue 3] babel, eslint)",
"Manually select features"
],
}]
inquirer.prompt(propmtList);
运行效果如下:
实现vue create效果
代码语言:txt复制const program = require('commander');
const inquirer = require('inquirer')
const propmtList = [{
type: 'list',
message: 'Please pick a preset',
name: 'preset',
choices: [
"Default ([Vue 2] babel, eslint)",
"Default (Vue 3 Preview) ([Vue 3] babel, eslint)",
"Manually select features"
],
}, {
type: 'checkbox',
message: 'Check the features needed for your project',
name: 'features',
choices: [{
name: 'Choose Vue version',
checked: true,
}, {
name: 'Babel',
checked: true,
}, {
name: 'TypeScript',
}, {
name: 'Progressive Web App (PWA) Support',
}, {
name: 'Router',
}, {
name: 'Vuex',
}, {
name: 'CSS Pre-processors',
}, {
name: 'Linter / Formatter',
checked: true,
}, {
name: 'Unit Testing',
checked: true,
}, {
name: 'E2E Testing',
checked: true,
}],
pageSize: 10,
}, {
type: 'list',
message: 'Choose a version of Vue.js that you want to start the project with',
name: 'version',
choices: [
"2.x",
"3.x (Preview)"
],
}, {
type: 'confirm',
message: 'Use history mode for router? (Requires proper server setup for index fallback in production)',
name: 'routerMode',
default: ''
}, {
type: 'list',
name: 'cssProcessor',
message: 'Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default)',
choices: [
"Sass/SCSS (with dart-sass)",
"Sass/SCSS (with node-sass)",
"Less",
"Stylus",
]
}, {
type: 'checkbox',
name: 'lint',
message: 'Pick additional lint features',
choices: [
"Lint on save",
"Lint and fix on commit",
]
}, {
type: 'list',
name: 'where',
message: 'Where do you prefer placing config for Babel, ESLint, etc.?',
choices: [
"In dedicated config files",
"In package.json",
]
}, {
type: 'confirm',
name: 'save',
message: 'Save this as a preset for future projects? ',
}];
program.usage('Usage: create [options] <app-name>')
.argument('[app-name]')
.showHelpAfterError()
.description('create a new project powered by vue-cli-service')
.option('-p, --preset <presetName>', 'Skip prompts and use saved or remote preset')
.option('-d, --default', 'Skip prompts and use default preset')
.option('-i, --inlinePreset <json>', 'Skip prompts and use inline JSON string as preset')
.option('-m, --packageManager <command>', 'Use specified npm client when installing dependencies')
.option('-r, --registry <url>', 'Use specified npm registry when installing dependencies (only for npm)')
.option('-g, --git [message]', 'Force git initialization with initial commit message')
.option('-n, --no-git', 'Skip git initialization')
.option('--merge', 'Merge target directory if it exists')
.option('-c, --clone', 'Use git clone when fetching remote preset')
.option('-x, --proxy <proxyUrl>', 'Use specified proxy when creating project')
.option('-b, --bare', 'Scaffold project without beginner instructions')
.option('--skipGetStarted', 'Merge target directory if it exists')
.action((name, options, command) => {
if (!name) {
program.help();
return;
}
inquirer.prompt(propmtList).then(answer => {
console.log(answer);
});
})
.parse();
运行效果
代码语言:txt复制node ./bin/my-cli.js create
没有输入工程名称时自动答应帮助信息:
代码语言:txt复制node ./bin/my-cli.js create hello
选择预设
选择特性
选择vue版本
是否使用history模式
选择css预处理器
选择eslint执行时机
选择babel config的存储位置
是否存为预设
打印用户的所有选择
总结
inquirer.js的实现简洁而优雅,文档清晰明了,对于脚手架开发的交互处理简单方便,定义了丰富的问题类型,和问题处理方法,简单易学,结合模拟实现vue-cli实现,有利于了解vue-cli是如何工作的。