之前我们了解了脚手架的基本实现步骤,以及如何解析命令行参数,下面来看看如何让你的终端更丰富。
以下库都是实现了ANSI转义序列 - 维基百科,自由的百科全书提供的标准,用于控制文本在终端上的光标位置、颜色和其他选项。
首先我们先来初体验原生ansi
// \x1b[图形在线码值\x1b[图形在线码值 + 操作代码 + 字符串内容
console.log("\x1b[4m\x1b[47m%s\x1b[0m", "ansi") // 输出带下划线白色背景的文字
console.log("\x1b[4F%s", "ansi2") // 光标上移一行显示
chalk
- ANSI转义码封装:自动处理终端兼容性
- 链式调用:
chalk.red.bold.underline('警告') - 16/256色支持:
chalk.rgb(255,0,0)('自定义红')
// 颜色组合
console.log(chalk.hex('#FF8800').bgBlack('黑色背景'));
// 样式叠加
const errorMsg = chalk.red.inverse.bold('[ERROR]');
// 多种类型颜色,只有最后一个生效
`chalk.red.yellow.green` 等价于 `chalk.green`
控制台精度条
import chalk from 'chalk';
function createProgressBar(total) {
let current = 0;
return {
update() {
current++;
const percent = (current / total * 100).toFixed(1);
if(current > total) return
const progress = chalk.green('■'.repeat(current))
+ chalk.gray('□'.repeat(total - current));
process.stdout.write(`\r${progress} ${chalk.yellow(percent)}%`);
}
};
}
const bar = createProgressBar(20);
const timer = setInterval(() => {
bar.update();
if(bar.current >= 20) clearInterval(timer);
}, 100);
如果想要使用原生ansi开发控制台文件样式,我们可以查看chalk提供的样式函数对应的ansi码值,快速实现我们的效果。
ora
在终端进行loading加载动画。
const spinner = ora('正在加载数据...').start();
setTimeout(() => spinner.stop(), 2000); // 正在加载数据直接消失
setTimeout(() => spinner.succeed('加载完成'), 2000); // 覆盖正在加载数据展示
// spinner.color 设置加载图标颜色
// spinner.text 修改加载文本
// spinner.prefixText 添加前置文本
// spinner.suffixText 添加后置文本
// spinner.suffixText 添加后置文本
还可以配置异步任务来进行处理,不需要我们处理ora的开始和结束,直接根据异步任务的结果即可更新loading状态。
async function init() {
const promise = new Promise((resolve, reject) => {
setTimeout(resolve, 2000);
});
await oraPromise(promise, {
failText: "失败了...",
successText: "成功了...",
text: "正在执行异步任务中..."
})
}
init()
我们还可以通过spinner调整loading的样式,提供的值可以在这里进行查找。
我们也可以自己去指定。
spinner:{
interval: 80, // 毫秒
frames: ["z", "h", "a", "n", "g"] // 指定interval时间段循环展示给定的字符
}
进度反馈机制
let progress = 0;
const spinner = ora({
text: '下载进度: 0%',
color: 'magenta'
}).start();
const updateInterval = setInterval(() => {
progress += 10;
spinner.text = `下载进度: ${chalk.green(progress)}%`;
if(progress >= 100) {
clearInterval(updateInterval);
spinner.succeed(chalk.bold('下载完成!'));
}
}, 500);
inquirer
node命令行交互工具。 由于一些命令,参数过程,用户难以记忆和配置。所以我们可以使用问答的方式,让用户选择,然后进行生成配置文件。例如vite等。
- 灵活的cli交互方式(提供很多的api)。
- 抹平平台间的差异。
现在我们来看下大致的使用方式
- type 提供了
input,number,confirm,list,rawlist,expand,checkbox,password,editor(windows直接打开记事本)问答方式。 - name 当前问答保存的键名。
- message 问答内容。
- default 问答默认值,如果是
list, rawlist, expand, checkbox其值应该是条目索引。 - choices 列表问答的选项
- validate 验证用户输入的内容,如果不通过将会给出提示。可直接返回提示信息。
- filter 过滤用户输入的内容。会直接修改answers中对应的属性的。
- transformer 修改用户输入的内容(起美化输出的作用),仅影响编辑时显示的内容。它不会修改 answers 哈希。
- when 当前问题是否被询问。
- pageSize 使用
list、rawList、expand或checkbox时将呈现的行数。 - prefix 更改问答前缀
- suffix 更改问答后缀
- loop 列表选择是否可以通过上下键循环切换。首尾项是否可以通过上下键切换。
- askAnswered 如果答案已存在,则强制提示问题。
- waitUserInput 启用/禁用在打开系统编辑器之前等待用户输入的标志。默认值为
true
inquirer.prompt([
{
type: 'input',
name: 'name',
message: '姓名:',
validate: input => input ? true : "姓名不能为空"
},
{
type: 'number',
name: 'age',
message: '年龄:',
min: 18,
max: 120,
default: 25
},
{
type: 'confirm',
name: 'sex',
message: '是否男生?',
},
{
type: 'list',
name: 'framework',
message: '选择框架:',
choices: [
{ name: 'React', value: 'react' },
{ name: 'Vue', value: 'vue' },
{ name: 'Angular', value: 'angular' },
new inquirer.Separator(), // 分隔线
{ name: '其他', value: 'other' }
],
loop: false,
default: 'react' // 可以是value值,也可以是选项条目索引
},
// 与 list 类似,但用户输入数字选择
{
type: 'rawlist',
name: 'theme',
message: '选择主题:',
choices: ['明亮', '暗黑', '系统默认']
},
{
type: 'expand',
name: 'action',
message: '请选择操作:',
choices: [
{ key: 'a', name: '添加用户', value: 'add' },
{ key: 'd', name: '删除用户', value: 'delete' },
{ key: 'e', name: '编辑用户', value: 'edit' },
new inquirer.Separator(),
{ key: 'x', name: '退出', value: 'exit' }
]
},
{
type: 'checkbox',
name: 'tools',
message: '选择开发工具:',
choices: [
{ name: 'ESLint', value: 'eslint', checked: true },
{ name: 'Prettier', value: 'prettier' },
{ name: 'TypeScript', value: 'ts', disabled: '已集成' },
{ name: 'Jest', value: 'jest' }
],
validate: choices => choices.length > 0 || '至少选择一项'
},
{
type: 'password',
name: 'password',
message: '设置密码:',
mask: '🔒',
validate: input => input.length >= 8 || '密码至少8位'
},
{
type: 'editor',
name: 'description',
message: '项目描述:',
postfix: '.md',
default: '# 项目描述\n\n请在此输入...'
}
]).then(answers => {
console.log('你的选择:', answers);
});
往期年度总结
- 在上海的忙碌一年,依旧充满憧憬(2024)
- 四年沿海城市,刚毕业,一年3家公司
- 七月仿佛又回到了那一年(2023年中总结)
- 一位初入职场前端仔的年度终结 <回顾2022,展望2023>
- 大学两年半的前端学习
往期文章
- 前端可以知道的录制浏览器标签页,没有黑魔法
- 一个关联本地页面镜像的功能,我了解到这些
- 啊,原来sessionStorage是这样的
- 如何像掘金编辑器一样粘贴图片即可上传服务器
- Nest装饰器全解析
- Nest世界中的AOP
- Nestjs如何解析http传输的数据
- 如何理解js的DOM事件系统
- 半年没看vue官网,3.5刚刚发布,趁机整理下
- 啊,你还在找一款强大的表格组件吗?
- 前端大量数据层级展示及搜索定位预览
- 如何从0开始认识m3u8(提取,解析及下载)
- 展示大量数据节点(tree),引发的一次性能排查
- ts装饰器的那点东西
- 这是你所知道的ts类型断言和类型守卫吗?
- TypeScript官网内容解读
- 经常使用ts的你,知道这些内容?
- 你有了解过原生css的scope?
- 现在比较常用的移动端调试你知道哪些?
- 众多跨标签页通信方式,你知道哪些?(二)
- 众多跨标签页通信方式,你知道哪些?
- 反调试吗?如何监听devtools的打开与关闭
- 因为原生,选择一家公司(前端如何防笔试作弊)
- 结合开发,带你熟悉package.json与tsconfig.json配置
- 如何优雅的在项目中使用echarts
- 如何优雅的做项目国际化
- 近三个月的排错,原来的憧憬消失喽
- 带你从0开始了解vue3核心(运行时)
- 带你从0开始了解vue3核心(computed, watch)
- 带你从0开始了解vue3核心(响应式)
- 3w+字的后台管理通用功能解决方案送给你
- 入职之前,狂补技术,4w字的前端技术解决方案送给你(vue3 + vite )
专栏文章
🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论, 支持一下博主~
公众号:全栈追逐者,不定期的更新内容,关注不错过哦!