基于inquirer实现一个控制台多级选择交互功能
创始人
2024-01-25 03:56:18

说在前面

🎈在前端脚手架工具中经常会看到控制台输入参数等操作。例如Vue-cli中初始化项目会提示选择一些参数等。所以在开发脚手架工具或者node控制台程序,就需要用到inquirer工具或者类似的工具。但是使用过inquirer工具的同学应该知道,目前inquirer工具支持的交互方式只有以下几种:input, number, confirm, list, rawlist, expand, checkbox, password, editor,最近自己在封装一个脚手架工具时需要使用到多级选择的功能来进行交互,但是看了一遍inquirer的文档,发现并没有可以直接使用的多级选择器类型交互,于是便开始基于inquirer进行二次封装,实现多级选择交互的功能。

效果展示

配置好参数后直接运行,效果如下图👇

在这里插入图片描述

实现思路

功能分解

首先我们先来分解一下这个功能,我们拥有一份树级结构的数据:

{'aa': [ 'aaa1', 'aaa2', 'aaa3', 'aaa4' ],'bb': [ 'bbb1', 'bbb2' ],'cc': [ 'ccc1' ]
}

我们需要实现以下这几个功能:

  • 1、按级展示对应的数据

接收的参数数据应该为树级结构的数据,我们应该对其进行分级展示(像电脑上的文件目录层级一样)。

  • 2、非叶子级的节点点击应该可以下钻

对于非叶子级的节点(及当前节点拥有子节点),我们对其点击应该进行下钻并展示其子节点的数据。

  • 3、叶子节点可以多选

遍历到叶子级别的数据时,我们需要支持多选功能。

  • 4、跨父节点数据保持

当我们进入一个叶子层级并进行了选择之后,我们还需要返回进入其他层级进行选择,这时我们需要保存在不同层级下选中的数据内容。

功能实现

将功能分解成几个小点之后,我们便可以按照分解好的功能点来逐点实现:

  • 1、按级展示对应的数据

这一点的功能其实就是一个单选选择框的功能,我们发现这点可以直接使用inquirer中类型为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-Xo1ZhUCX-1668566115879)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/922dda3d632a48c09de9c7c7d9dee17b~tplv-k3u1fbpfcp-watermark.image?)]

这里我们只需要将传入的树级结构数据遍历到的层级的key提出重新组成list的参数即可:

//叶子节点层级的数据应该为数组类型的数据,所以可以通过isArray来判断当前层级是否为叶子层级
optionTemp.type = Array.isArray(obj) ? 'checkbox' : 'list';
optionTemp.choices = Array.isArray(obj) ? obj : Object.keys(obj);
  • 2、非叶子级的节点点击应该可以下钻

遍历到非叶子层级时,我们需要递归处理其子级节点数据,非叶子层级的列表我们使用的是list单选列表来展示,叶子层级的数据我们使用的是checkbox多选列表来展示,所以我们可以根据当前展示的类别来进行不同的递归处理。

(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);
}
  • 3、叶子节点可以多选

叶子节点列表我们需要支持多选功能,这个功能我们可以直接复用inquirer中类型为checkbox的复选框来实现。

const options1 = [{type: 'checkbox',name: 'choice',message: 'your choice:',default: 0,choices: [{ value: 1, name: '张三' },{ value: 2, name: '李四' }]
}];
const j = new JInquirer(options1);
const res = j.prompt().then(res=>{console.log(res);
});

运行结果如下图:

在这里插入图片描述

可以使用空格进行选择,ctrl + a 可以全选,ctrl + i 进行反选,回车确认选择内容。

  • 4、跨父节点数据保持

这里我们可以使用两个方案来实现:

(1)使用函数入参来记录选中的数据

我们可以将每次选中的数据在函数的入参中传入,每次回调时更新该参数即可。

(2)在类中添加一个参数来记录。

直接在类中添加一个公共参数来记录,这样读取会比较方便。

比较了两种方法后,我觉得还是直接在类中添加一个公共参数来记录,这样读取会比较方便,所以最后选择了使用方案二来实现该功能。

class JInquirer{constructor(options,config){this.options = options; //参数this.config = config || {}; //配置this.answer = {}; //输出结果容器this.tempList = {}; //中间值临时容器变量}
}

使用方法

1、安装依赖

npm install @jyeontu/j-inquirer

2、在代码中引用

const JInquirer = require('@jyeontu/j-inquirer');

3、示例代码

const options1 = [{type:"input",message:"请输入你的姓名:",name:"name",notNull:true},{type: 'expandList',name: 'choice',message: '多级选择器测试:',choices:{'aa': [ 'aaa1', 'aaa2', 'aaa3', 'aaa4' ],'bb': [ 'bbb1', 'bbb2' ],'cc': [ 'ccc1' ]}
}];
const j = new JInquirer(options1);
const res = j.prompt().then(res=>{console.log(res);
});

源码地址

https://gitee.com/zheng_yongtao/node-scripting-tool/tree/master/src/JInquirer

觉得有帮助的同学可以帮忙给我点个star,感激不尽~~~
有什么想法或者改良可以给我提个pr,十分欢迎~~~
有什么问题都可以在评论告诉我~~~

往期精彩

面试官:不使用canvas怎么实现一个刮刮卡效果?

vue封装一个3D轮播图组件

vue实现一个鼠标滑动预览视频封面组件(精灵图版本)

node封装一个图片拼接插件

基于inquirer封装一个控制台文件选择器

node封装一个控制台进度条插件

密码太多不知道怎么记录?不如自己写个密码箱小程序

微信小程序实现一个手势图案锁组件

vue封装一个弹幕组件

为了学(mo)习(yu),我竟开发了这样一个插件

程序员的浪漫之——情侣日常小程序

vue简单实现词云图组件

说在后面

🎉这里是JYeontu,喜欢算法,GDCPC打过卡;热爱羽毛球,大运会打过酱油。毕业一年,两年前端开发经验,目前担任H5前端开发,算法业余爱好者,有空会刷刷算法题,平时喜欢打打羽毛球🏸 ,也喜欢写些东西,既为自己记录📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解🙇,写错的地方望指出,定会认真改进😊,在此谢谢大家的支持,我们下文再见🙌。

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
公司优势怎么写比较好 如何描述... 我对企业竞争优势的理解和总结
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
乌拉是什么意思 乌托邦是什么意... 相信对俄罗斯有一定了解的朋友肯定不会对“乌拉”(Ура,读成“歪--屁--哎”的朋友请出门左转不送)...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...