基于inquirer实现一个控制台多级选择交互功能

说在前面
在前端脚手架工具中经常会看到控制台输入参数等操作 。例如Vue-cli中初始化项目会提示选择一些参数等 。所以在开发脚手架工具或者node控制台程序,就需要用到工具或者类似的工具 。但是使用过工具的同学应该知道,目前工具支持的交互方式只有以下几种:input, , , list, , , , , ,最近自己在封装一个脚手架工具时需要使用到多级选择的功能来进行交互,但是看了一遍的文档,发现并没有可以直接使用的多级选择器类型交互,于是便开始基于进行二次封装,实现多级选择交互的功能 。
效果展示
配置好参数后直接运行,效果如下图
实现思路 功能分解
首先我们先来分解一下这个功能,我们拥有一份树级结构的数据:
{'aa': [ 'aaa1', 'aaa2', 'aaa3', 'aaa4' ],'bb': [ 'bbb1', 'bbb2' ],'cc': [ 'ccc1' ]}
我们需要实现以下这几个功能:
接收的参数数据应该为树级结构的数据,我们应该对其进行分级展示(像电脑上的文件目录层级一样) 。
对于非叶子级的节点(及当前节点拥有子节点),我们对其点击应该进行下钻并展示其子节点的数据 。
遍历到叶子级别的数据时,我们需要支持多选功能 。
当我们进入一个叶子层级并进行了选择之后,我们还需要返回进入其他层级进行选择,这时我们需要保存在不同层级下选中的数据内容 。
功能实现
将功能分解成几个小点之后,我们便可以按照分解好的功能点来逐点实现:
这一点的功能其实就是一个单选选择框的功能,我们发现这点可以直接使用中类型为list的组件来实现 。
const options = [{type: 'list',name: 'choice',message: 'your choice:',default: 0,choices: [{ value: 1, name: '张三' },{ value: 2, name: '李四' }]}];const j = new JInquirer(options);const res = j.prompt().then(res=>{console.log(res);});
运行的结果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img--79)(~tplv--.image?)]
这里我们只需要将传入的树级结构数据遍历到的层级的key提出重新组成list的参数即可:
//叶子节点层级的数据应该为数组类型的数据,所以可以通过isArray来判断当前层级是否为叶子层级optionTemp.type = Array.isArray(obj) ? 'checkbox' : 'list';optionTemp.choices = Array.isArray(obj) ? obj : Object.keys(obj);
遍历到非叶子层级时,我们需要递归处理其子级节点数据,非叶子层级的列表我们使用的是list单选列表来展示,叶子层级的数据我们使用的是多选列表来展示,所以我们可以根据当前展示的类别来进行不同的递归处理 。
(1)非叶子层级
对于非叶子层级的数据,我们点击应该进入下一级:
await this.chooseExpandList(op,deep + 1,pre+answer[option.name],originOption);
(2)叶子层级
对于叶子层级的数据,我们选择完成后应该回到根节点级别继续选择:
await this.chooseExpandList(originOption,0,'',originOption);
完整关键代码如下:
if(optionTemp.type === 'list'){if(pre) pre += '/';const op = {...option};op.choices = obj[answer[option.name]];await this.chooseExpandList(op,deep + 1,pre+answer[option.name],originOption);}else{this.tempList[pre] = answer[option.name];await this.chooseExpandList(originOption,0,'',originOption);}