高级前端篇-脚手架开发

何为脚手架

脚手架做为前端基建的一环,大家熟知的有比如vue-cli , @vue/cli , create-react-app , vite还有其他很多社区的脚手架。通过这些脚手架我们可以很快的生成需要的项目模版,可以在此基础上快速的开发项目。

然而这些脚手架只是些通用解决方案,他们不关注上层的设计,比如:统一ajax封装,library external,docker的构建,模板工程约束,固化团队风格的代码规范约束,公共依赖的统一控制,服务的监控报警,拨测,强缓存控制,CDN接入。

  • 狭义上讲,脚手架是一个可以快速地使用配置好的工程模板初始化工程的工具,避免重复工作,为开发者提供便利;

  • 广义上讲,脚手架是一个完善的面向整个前端项目生命周期的工程解决方案,从初始化、开发调试到构建部署,都提供了一系列的工具或者规范,并且集成到一个"工具"中,开发者只需关心业务逻辑开发即可,这工具也可以称为"脚手架"。

我们可以通过自己自定义的脚手架来统一规范,减小开发成本,脚手架作为前端基础建设的一环,具体可看下图:

为什么需要脚手架

现在大多数开发者已经习惯使用 vue-cli / create-react-app 等工具来快速初始化一个项目,不妨先看看前端项目初始化的一个发展历程:

  1. 远古时代。手动创建前端三件套:index.html/index.js/index.css,在 index.html 里分别引入 index.js 和 index.css
  2. 石器时代。将项目模板代码托管到 Git/SVN 上,使用的时候先手动将代码拉到本地,然后修改文件夹名以及项目中的配置
  3. 青铜时代。通过脚本,自动化做了一些事情:拉取项目模板、配置项目信息等
  4. 蒸汽时代。形成一套完整的命令行工具,比如 vue-cli/ create-react-app 等
  5. 工业时代。在 cra/vue-cli 的基础上定制个性能力,接入自定义模板、自动化 Git 流程、数据采集等
  6. 现代。脚手架已经跳出终端(命令行),有了可视化、WebIDE 等方案,通过更为方便的交互即可完成项目的初始化

从这样一个发展历程可以看出,脚手架解决的核心问题就是 ------ 帮助开发者更方便地初始化项目,这也就是为什么需要脚手架。总结来说,脚手架最重要的作用有两点:

  1. 提高效率。之前初始化一个可用的项目可能需要 1 个小时甚至更久,到如今只需要敲个命令或者点下鼠标然后伸个懒腰就搞定了
  2. 降低成本。比如创建文件、配置项目信息等都是重复工作,开发者没必要花精力在这些可以自动化的事情上

在完整的前端工程体系中,脚手架起到至关重要的作用。

脚手架构建

一个脚手架应该具备哪些功能

bash 复制代码
我在gitee上分享一个,自己写的基于lerna与Commander简易的企业级脚手架,大家可以借阅一下:
https://gitee.com/MrHuang-junzhe/huang-cli-dev.git

脚手架初始化:

js 复制代码
async function core() {
  try {
    await prepare(); //脚手架检查阶段
    registerCommands(); //脚手架命令初始化
  } catch (e) {
    log.error(e.message);
  }
}
  1. 一个完整的脚手架应该分为:预开发环节 ⇒ 开发环节 ⇒ 构建环节 ⇒ 预提交环节 ⇒ 发布环节
    • 检查阶段
    • 命令初始化(运用脚手架框架Commander)
    • 构建阶段:Node.js内置的[child_process模块**]可以用于执行系统命令。通过这个模块,你可以在Node.js应用程序中执行外部程序。常用的方法包括[exec**]、[spawn**]和[execFile**]
    • 预检查阶段:调用git的api来对代码进行预检查
    • 发布阶段:脚手架会对项目进行构建并推到远程仓库(gitFlow云构建)

2.检查阶段的代码如下,这里只对流程做一个讲解,详情代码看下文

js 复制代码
async function prepare() {
checkPkgVersion(); //检查版本号
checkRoot(); //权限降级,避免权限报错
checkUserHome(); //判断当前主目录是否存在
// checkInputArgs()//检查参数,是否开启debug模式
checkEnv(); //检查环境变量
await checkGlobalUpdate(); //检查当前脚手架是否为最新版本
}

这里涉及重点的npm库有server,检查npm版本号

3.开发阶段,运用了Commander脚手架框架来做脚手架的初始化,具体可扩展

js 复制代码
function registerCommands() {
program
 .name(Object.keys(pkg.bin)[0])
 .usage("<command> [options]")
 .version(pkg.version)
 .option("-d, --debug", "开启调试模式", false)
 .option("-tp, --targetPath <targetPath>", "是否指定本地调试文件路径", "");
//初始化命令
program
 .command("init [projectName]")
 .description("初始化项目")
 .option("-f, --force", "是否强制初始化项目")
 .action(exec); //实现exec动态加载init

//debug模式注册
program.on("option:debug", function () {
 if (program.opts().debug) process.env.LOG_LEVEL = "verbose";
 else process.env.LOG_LEVEL = "info";
 log.level = process.env.LOG_LEVEL;
});

//对未知命令的监听
program.on("command:*", function (obj) {
 const availableCommands = program.commands.map((cmd) => cmd.name());
 console.log(colors.red(`未知的命令:${obj[0]}`));
 console.log(colors.red(`可用的命令:${availableCommands.join(",")}`));
});
//判断有无options
// process.argv.length<3?program.outputHelp():program.parse(process.argv)
program.parse(process.argv);
if (program.args && program.args.length < 1) program.outputHelp();
}

多包管理工具

说到npm库,就离不开多包管理,目前常用的多包管理体系有:

  1. npm:高版本的npm自带多包管理
  2. pnpm+monnra架构,进行多包管理
  3. lerna,一个常用的多包管理工具

为什么需要用到多包管理工具?因为本地项目需要调试和管理多个项目之间的依赖关系

新版本NPM,多包管理详解

1.package.json文件刨析,详情请看下图,不多做赘述

脚手架的入口文件,主要通过里面的bin属性来进入,在本地npm link建立软连接

npm link命令(环境变量软连接):我们本地化开发 npm package 不可能每次改了代码,都发布到 npm 商场去,所以 npm 提供给我们 npm-link 这个命令用来进行本地化开发。

json 复制代码
"bin": {
 "huang-cli-dev": "core/cli/bin/index.js" //这样就将huang-cli-dev命令连接到了本地
},

什么是 npm Workspace

npm Workspace 是 npm 从 v7 版本开始引入的一项特性,它允许在一个顶级的 package.json 中管理多个子项目(也就是工作空间)。这种方式有助于组织和管理具有多个相关包的大型项目,能够简化依赖管理、脚本执行等操作,提高开发效率。

什么是 Monorepo

Monorepo(单体仓库)是一种将多个相关项目(包)存储在一个代码仓库中的管理方式。在 Monorepo 架构下,不同的包可以共享代码、依赖和构建工具,便于统一管理和协同开发。

主要优势

  1. 简化依赖管理:可以在根项目中统一管理所有子项目的依赖,避免重复安装相同的依赖,节省磁盘空间和安装时间。
  2. 方便脚本执行:可以在根项目中运行所有子项目的脚本,而不需要分别进入每个子项目的目录。
  3. 本地包引用:子项目之间可以方便地相互引用,而不需要发布到 npm 仓库。

使用步骤

1. 初始化项目

首先,创建一个新的项目目录,并在该目录下初始化一个新的 npm 项目:

bash

perl 复制代码
mkdir my-monorepo
cd my-monorepo
npm init -y
2. 配置 Workspace

在根目录的 package.json 中添加 workspaces 字段,指定包含子项目的目录。例如:

json

json 复制代码
{
  "name": "my-monorepo",
  "version": "1.0.0",
  "workspaces": [
    "packages/*"
  ]
}

上述配置表示 packages 目录下的所有子目录都是工作空间。

3. 创建子项目

packages 目录下创建一些子项目:

bash

bash 复制代码
mkdir packages
cd packages
mkdir package-a package-b
cd package-a
npm init -y
cd ../package-b
npm init -y
4. 安装依赖

可以在根目录下为所有子项目统一安装依赖。例如,安装 lodash

bash

bash 复制代码
cd ../../
npm install lodash

这会将 lodash 安装到根目录的 node_modules 中,所有子项目都可以共享这个依赖。

5. 子项目间相互引用

假设 package-a 依赖于 package-b,可以在 package-apackage.json 中添加对 package-b 的依赖:

bash

css 复制代码
cd packages/package-a
npm install package-b --workspace

这会在 package-apackage.json 中添加对 package-b 的依赖,并且会在 package-anode_modules 中创建一个指向 package-b 的符号链接。

高级用法

选择性安装依赖

可以只在特定的子项目中安装依赖:

bash

css 复制代码
npm install react --workspace=package-a
发布所有子项目

如果需要将所有子项目发布到 npm 仓库,可以使用以下命令:

bash

css 复制代码
npm publish --workspaces

注意事项

  • Node.js 版本 :建议使用 Node.js v14 或更高版本,以确保 npm Workspace 功能正常工作。

  • 符号链接:子项目之间的依赖是通过符号链接实现的,在某些情况下可能会导致文件路径解析问题,需要注意。

通过使用 npm Workspace,可以更高效地管理和开发包含多个相关包的大型项目。

在 npm Workspace 里,子项目之间能够轻松地相互引用,从而实现代码的共享

通过lerna管理多包项目

在这里推荐一篇神文,具体操作请看它:juejin.cn/post/732861...

Lerna 是一个用于管理包含多个包(package)的 JavaScript 项目的工具,通常用于管理 Monorepo(单体仓库)架构的项目。在 Monorepo 中,多个相关的包被放在同一个代码仓库中,Lerna 可以帮助开发者更高效地管理这些包之间的依赖、版本发布、代码构建等操作。

Lerna 的作用及详细解读

1. 依赖管理
  • 集中管理依赖 :在 Monorepo 中,多个包可能会有相同的依赖。Lerna 可以帮助在根目录集中管理这些依赖,避免每个子包都重复安装相同的依赖,节省磁盘空间和安装时间。例如,多个子包都依赖于 lodash,可以在根目录的 package.json 中安装 lodash,所有子包都可以共享这个依赖。
  • 自动处理本地包依赖:当一个子包依赖于另一个子包时,Lerna 可以自动处理这种本地包之间的依赖关系,通过符号链接的方式让子包之间可以方便地相互引用,而不需要发布到 npm 仓库。
2. 版本管理
  • 独立版本控制:Lerna 支持两种版本管理模式,其中一种是 "独立模式"(Independent mode)。在独立模式下,每个子包可以有自己独立的版本号,开发者可以根据每个包的实际情况单独更新版本,适合不同子包有不同发布节奏的项目。
  • 固定版本控制:另一种是 "固定模式"(Fixed/Locked mode)。在固定模式下,所有子包共享一个版本号,当任何一个子包有更新时,所有子包的版本号都会同步更新。这种模式适合所有子包需要保持版本一致性的项目。
3. 代码发布
  • 批量发布 :Lerna 可以帮助开发者批量发布多个子包到 npm 仓库。它会自动检测哪些包有更新,然后根据配置的版本管理模式更新版本号,并将更新后的包发布到 npm。例如,使用 lerna publish 命令可以一键完成所有有更新的子包的版本更新和发布操作。
  • 自动生成变更日志:在发布过程中,Lerna 可以根据代码的提交信息自动生成变更日志(Changelog),记录每个包的版本更新内容,方便开发者和使用者了解项目的更新情况。
4. 脚本执行
  • 并行执行脚本 :Lerna 可以在所有子包中并行执行相同的脚本,提高执行效率。例如,在所有子包中运行测试脚本,可以使用 lerna run test 命令,Lerna 会同时在每个子包中执行 test 脚本。
  • 选择性执行脚本 :也可以指定只在部分子包中执行脚本。例如,lerna run build --scope=package-a 表示只在 package-a 子包中执行 build 脚本。
5. 代码同步
  • 保持代码一致性:在 Monorepo 中,多个子包可能会有一些公共的代码或配置。Lerna 可以帮助确保这些公共部分在各个子包中保持一致,避免出现代码重复和不一致的问题。例如,可以将公共的配置文件放在根目录,然后在子包中引用这些配置。

一大包脚手架必备Node优质库来袭

Commander(脚手架实现命令交互的框架)

Commander.js 是一个用于快速创建 Node.js 命令行工具的强大库,它可以帮助开发者轻松解析命令行参数、定义命令和选项,使命令行工具的开发变得更加高效和便捷。以下是对 Commander.js 库的详细介绍:

安装

在开始使用 Commander.js 之前,需要先进行安装。可以使用 npm 或 yarn 进行安装:

bash

csharp 复制代码
npm install commander
# 或者
yarn add commander

基本使用

下面是一个简单的示例,展示了如何使用 Commander.js 创建一个基本的命令行工具:

javascript

arduino 复制代码
const { program } = require('commander');

// 设置版本号
program.version('1.0.0');

// 解析命令行参数
program.parse(process.argv);

在上述代码中,首先引入 Commander.jsprogram 对象,然后使用 version 方法设置命令行工具的版本号,最后使用 parse 方法解析命令行参数。将上述代码保存为 cli.js,在命令行中运行 node cli.js --version,就可以看到输出的版本号。

定义命令

Commander.js 允许开发者定义多个命令,每个命令可以有自己的参数和选项。以下是一个定义命令的示例:

javascript

javascript 复制代码
const { program } = require('commander');

// 定义一个名为 "add" 的命令
program
  .command('add <num1> <num2>')
  .description('Add two numbers')
  .action((num1, num2) => {
    const result = parseInt(num1) + parseInt(num2);
    console.log(`The result is: ${result}`);
  });

// 解析命令行参数
program.parse(process.argv);

在上述代码中,使用 command 方法定义了一个名为 add 的命令,该命令接受两个参数 <num1><num2>。使用 description 方法为命令添加描述信息,使用 action 方法定义命令执行时的回调函数。将上述代码保存为 cli.js,在命令行中运行 node cli.js add 2 3,就可以看到输出的计算结果。

定义选项

除了命令和参数,Commander.js 还支持定义选项。选项可以用于修改命令的行为或提供额外的配置信息。以下是一个定义选项的示例:

javascript

javascript 复制代码
const { program } = require('commander');

// 定义一个名为 "greet" 的命令,并添加一个选项
program
  .command('greet')
  .description('Greet someone')
  .option('-n, --name <name>', 'Specify the name to greet')
  .action((options) => {
    const name = options.name || 'World';
    console.log(`Hello, ${name}!`);
  });

// 解析命令行参数
program.parse(process.argv);

在上述代码中,使用 option 方法为 greet 命令添加了一个选项 -n, --name <name>,该选项用于指定要问候的人的名字。在 action 方法中,可以通过 options 对象获取选项的值。将上述代码保存为 cli.js,在命令行中运行 node cli.js greet -n John,就可以看到输出的问候语。

处理命令行参数

Commander.js 会自动解析命令行参数,并将其传递给相应的命令和选项。可以通过 process.argv 数组获取原始的命令行参数,也可以通过 program 对象的属性和方法获取解析后的参数和选项。以下是一个处理命令行参数的示例:

javascript

arduino 复制代码
const { program } = require('commander');

// 定义一个全局选项
program
  .option('-d, --debug', 'Enable debug mode')
  .parse(process.argv);

// 获取选项的值
const options = program.opts();
if (options.debug) {
  console.log('Debug mode is enabled.');
}

在上述代码中,使用 option 方法定义了一个全局选项 -d, --debug,用于启用调试模式。在代码中,可以通过 program.opts() 方法获取解析后的选项对象,并根据选项的值执行相应的操作。

帮助信息和版本信息

Commander.js 会自动生成命令行工具的帮助信息和版本信息。可以使用 --help 选项查看帮助信息,使用 --version 选项查看版本信息。以下是一个示例:

javascript

javascript 复制代码
const { program } = require('commander');

// 设置版本号
program.version('1.0.0');

// 定义一个命令
program
  .command('hello')
  .description('Say hello')
  .action(() => {
    console.log('Hello!');
  });

// 解析命令行参数
program.parse(process.argv);

在命令行中运行 node cli.js --help,可以看到自动生成的帮助信息;运行 node cli.js --version,可以看到设置的版本号。

总结

Commander.js 是一个功能强大、易于使用的 Node.js 命令行工具开发库,它提供了丰富的功能,包括命令定义、选项定义、参数解析、帮助信息生成等。通过使用 Commander.js,可以快速创建出功能完善、易用的命令行工具。

npmlog(node自定义log命令库)

npmlog 是一个用于在 Node.js 应用程序中进行日志记录的轻量级库,它专为 npm 自身的日志记录需求而设计,具有简单易用、灵活配置等特点。

semver(查询包版本库)

semver 能对npm的版本字符进行验证,判断是否是最新的npm版本等功能

npminstall(下载包的库)

npminstall 是一个用于快速安装 npm 包的 Node.js 库,它是 npm install 命令的高性能替代方案,由阿里巴巴团队开发。相比于原生的 npm installnpminstall 具有更快的安装速度、更好的磁盘空间利用效率以及更稳定的安装过程。以下是对 npminstall 库的详细介绍。

安装

使用 npm 进行安装:

bash

复制代码
npm install npminstall

基本使用

以下是一个简单的示例,展示如何使用 npminstall 在 Node.js 代码中安装 npm 包:

javascript

typescript 复制代码
const npminstall = require('npminstall');

npminstall({
  root: __dirname, // 指定安装的根目录
  pkgs: [
    { name: 'lodash', version: '^4.17.21' } // 指定要安装的包及其版本
  ]
})
.then(() => {
  console.log('Packages installed successfully');
})
.catch((err) => {
  console.error('Installation failed:', err);
});

在上述代码中,首先引入 npminstall 模块,然后调用 npminstall 函数并传入一个配置对象。配置对象中,root 指定了安装的根目录,pkgs 是一个数组,包含了要安装的包及其版本信息。安装成功后会输出提示信息,安装失败则会输出错误信息。

配置选项

npminstall 函数接受一个配置对象,以下是一些常用的配置选项:

1. root
  • 类型string

  • 作用:指定安装的根目录,默认为当前工作目录。

javascript

css 复制代码
npminstall({
  root: '/path/to/your/project'
});
2. pkgs
  • 类型Array<{ name: string, version: string }>

  • 作用:指定要安装的包及其版本。

javascript

php 复制代码
npminstall({
  pkgs: [
    { name: 'lodash', version: '^4.17.21' },
    { name: 'axios', version: '^0.21.1' }
  ]
});
3. registry
  • 类型string

  • 作用 :指定 npm 包的注册表地址,默认为 https://registry.npmjs.org

javascript

css 复制代码
npminstall({
  registry: 'https://registry.npmmirror.com'
});
4. production
  • 类型boolean

  • 作用 :是否只安装生产环境依赖,默认为 false

javascript

php 复制代码
npminstall({
  production: true
});
5. storeDir
  • 类型string

  • 作用:指定包的存储目录,用于缓存已下载的包,提高安装速度。

javascript

css 复制代码
npminstall({
  storeDir: '/path/to/store/dir'
});

高级用法

并行安装

npminstall 支持并行安装多个包,从而提高安装速度。默认情况下,npminstall 会自动进行并行安装。

javascript

php 复制代码
npminstall({
  pkgs: [
    { name: 'lodash', version: '^4.17.21' },
    { name: 'axios', version: '^0.21.1' },
    { name: 'react', version: '^17.0.2' }
  ]
});
事件监听

npminstall 提供了一些事件,允许开发者在安装过程中进行监听和处理。例如,可以监听 installing 事件来获取安装进度信息:

javascript

typescript 复制代码
const npminstall = require('npminstall');

npminstall({
  root: __dirname,
  pkgs: [
    { name: 'lodash', version: '^4.17.21' }
  ]
})
.on('installing', (pkg) => {
  console.log(`Installing ${pkg.name}@${pkg.version}`);
})
.then(() => {
  console.log('Packages installed successfully');
})
.catch((err) => {
  console.error('Installation failed:', err);
});

package.json 结合使用

可以通过读取 package.json 文件中的依赖信息,动态地安装所需的包:

javascript

ini 复制代码
const fs = require('fs');
const path = require('path');
const npminstall = require('npminstall');

const packageJsonPath = path.join(__dirname, 'package.json');
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));

const dependencies = Object.entries(packageJson.dependencies || {}).map(([name, version]) => ({ name, version }));
const devDependencies = Object.entries(packageJson.devDependencies || {}).map(([name, version]) => ({ name, version }));

const allDependencies = [...dependencies, ...devDependencies];

npminstall({
  root: __dirname,
  pkgs: allDependencies
})
.then(() => {
  console.log('Packages installed successfully');
})
.catch((err) => {
  console.error('Installation failed:', err);
});

inquirer(自定义交互式命令库)

inquirer 是一个流行的 Node.js 库,用于在命令行界面(CLI)中创建交互式提示,它可以让开发者轻松地从用户那里获取输入,实现友好的人机交互。以下是对 inquirer 库的详细介绍。

基本使用

以下是一个简单的示例,展示了如何使用 inquirer 从用户那里获取输入:

javascript

ini 复制代码
const inquirer = require('inquirer');

// 定义问题
const questions = [
  {
    type: 'input',
    name: 'name',
    message: 'What is your name?'
  }
];

// 发起询问
inquirer.prompt(questions).then(answers => {
  console.log(`Hello, ${answers.name}!`);
});

在上述代码中,首先引入 inquirer 模块,然后定义了一个包含一个问题的数组 questions。每个问题是一个对象,包含 type(问题类型)、name(答案存储的键名)和 message(显示给用户的提示信息)。最后使用 inquirer.prompt 方法发起询问,该方法返回一个 Promise,当用户回答完所有问题后,会在 then 方法中得到一个包含所有答案的对象。

问题类型

1. input
  • 作用:允许用户输入任意文本。

javascript

ini 复制代码
const inquirer = require('inquirer');

const questions = [
  {
    type: 'input',
    name: 'email',
    message: 'Please enter your email address:'
  }
];

inquirer.prompt(questions).then(answers => {
  console.log(`Your email is: ${answers.email}`);
});
2. confirm
  • 作用 :让用户确认一个选项,用户可以输入 yn 来表示同意或不同意。

javascript

ini 复制代码
const inquirer = require('inquirer');

const questions = [
  {
    type: 'confirm',
    name: 'subscribe',
    message: 'Do you want to subscribe to our newsletter?'
  }
];

inquirer.prompt(questions).then(answers => {
  if (answers.subscribe) {
    console.log('You have subscribed to our newsletter.');
  } else {
    console.log('You have declined to subscribe.');
  }
});
3. list
  • 作用:提供一个选项列表,让用户选择其中一个。

javascript

ini 复制代码
const inquirer = require('inquirer');

const questions = [
  {
    type: 'list',
    name: 'color',
    message: 'Choose your favorite color:',
    choices: ['Red', 'Green', 'Blue']
  }
];

inquirer.prompt(questions).then(answers => {
  console.log(`Your favorite color is: ${answers.color}`);
});
4. rawlist
  • 作用 :与 list 类似,但使用数字作为选择项,用户可以直接输入数字来选择。

javascript

ini 复制代码
const inquirer = require('inquirer');

const questions = [
  {
    type: 'rawlist',
    name: 'size',
    message: 'Select your T-shirt size:',
    choices: ['S', 'M', 'L', 'XL']
  }
];

inquirer.prompt(questions).then(answers => {
  console.log(`Your T-shirt size is: ${answers.size}`);
});
5. checkbox
  • 作用:允许用户从多个选项中选择多个。

javascript

ini 复制代码
const inquirer = require('inquirer');

const questions = [
  {
    type: 'checkbox',
    name: 'fruits',
    message: 'Select your favorite fruits:',
    choices: ['Apple', 'Banana', 'Orange', 'Grape']
  }
];

inquirer.prompt(questions).then(answers => {
  console.log(`Your favorite fruits are: ${answers.fruits.join(', ')}`);
});
6. password
  • 作用:用于输入密码,输入的内容会被隐藏。

javascript

ini 复制代码
const inquirer = require('inquirer');

const questions = [
  {
    type: 'password',
    name: 'password',
    message: 'Enter your password:'
  }
];

inquirer.prompt(questions).then(answers => {
  console.log('Password entered successfully.');
});

高级用法

验证用户输入

可以通过 validate 函数对用户的输入进行验证,确保输入符合要求。

javascript

javascript 复制代码
const inquirer = require('inquirer');

const questions = [
  {
    type: 'input',
    name: 'age',
    message: 'How old are you?',
    validate: function(value) {
      const valid = !isNaN(parseFloat(value)) && parseInt(value) > 0;
      return valid ? true : 'Please enter a valid age.';
    }
  }
];

inquirer.prompt(questions).then(answers => {
  console.log(`You are ${answers.age} years old.`);
});
根据用户回答动态显示问题

可以根据用户对前一个问题的回答来决定是否显示后续问题,通过 when 函数实现。

javascript

rust 复制代码
const inquirer = require('inquirer');

const questions = [
  {
    type: 'confirm',
    name: 'hasPet',
    message: 'Do you have a pet?'
  },
  {
    type: 'input',
    name: 'petName',
    message: 'What is your pet's name?',
    when: answers => answers.hasPet
  }
];

inquirer.prompt(questions).then(answers => {
  if (answers.hasPet) {
    console.log(`Your pet's name is ${answers.petName}.`);
  } else {
    console.log('You don't have a pet.');
  }
});

inquirer 库为 Node.js 开发者提供了丰富的交互式提示功能,通过多种问题类型、输入验证和动态问题显示等特性,可以创建出功能强大、用户体验良好的命令行界面。无论是构建简单的脚本还是复杂的 CLI 工具,inquirer 都是一个非常实用的工具。

相关推荐
拖孩19 分钟前
【Nova UI】十五、打造组件库之滚动条组件(上):滚动条组件的起步与进阶
前端·javascript·css·vue.js·ui组件库
Hejjon32 分钟前
Vue2 elementUI 二次封装命令式表单弹框组件
前端·vue.js
小堃学编程1 小时前
前端学习(3)—— CSS实现热搜榜
前端·学习
Wannaer1 小时前
从 Vue3 回望 Vue2:响应式的内核革命
前端·javascript·vue.js
不灭锦鲤2 小时前
xss-labs靶场基础8-10关(记录学习)
前端·学习·xss
Bl_a_ck2 小时前
--openssl-legacy-provider is not allowed in NODE_OPTIONS 报错的处理方式
开发语言·前端·web安全·网络安全·前端框架·ssl
懒羊羊我小弟2 小时前
手写符合Promise/A+规范的Promise类
前端·javascript
互联网搬砖老肖2 小时前
Web 架构之负载均衡会话保持
前端·架构·负载均衡
肥肥呀呀呀3 小时前
在Flutter上如何实现按钮的拖拽效果
前端·javascript·flutter
Zero1017133 小时前
【React的useMemo钩子详解】
前端·react.js·前端框架