编写自己的Yeoman生成器-3.与用户交互

您的生成器将与最终用户进行大量交互。默认情况下,Yeoman在终端上运行,但它也支持不同工具可以提供的自定义用户界面。例如,没有什么能阻止Yeoman生成器在编辑器或独立应用程序之类的图形工具中运行。

为了实现这种灵活性,Yeoman提供了一组用户界面元素抽象。作为作者,您有责任在与最终用户交互时仅使用这些抽象。使用其他方法可能会阻止您的生成器在不同的Yeoman工具中正确运行。

例如,永远不要使用console.log()或process.stdout.write()输出内容很重要。使用它们会隐藏不使用终端的用户的输出。相反,始终依赖于UI通用this.log()方法,其中this是当前生成器的上下文。

用户互动

提示

提示是生成器与用户交互的主要方式。提示模块由Inquirer.js提供,您应该参考其API以获取可用的提示选项列表。

prompt方法是异步的并返回一个Promise。您需要从任务中返回Promise,以便在运行下一个任务之前等待其完成。(详细了解异步任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module.exports = class extends Generator {
async prompting() {
const answers = await this.prompt([{
type : 'input',
name : 'name',
message : 'Your project name',
default : this.appname // Default to current folder name
}, {
type : 'confirm',
name : 'cool',
message : 'Would you like to enable the Cool feature?'
}]);

this.log('app name', answers.name);
this.log('cool feature', answers.cool);
}
};

请注意,我们使用prompting队列来询问用户的反馈。

在稍后阶段使用用户answers

一种非常常见的情况是在稍后阶段使用用户答案,例如在writing队列中。这可以通过将它们添加到this上下文中来轻松实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
module.exports = class extends Generator {
async prompting() {
this.answers = await this.prompt([{
type : 'confirm',
name : 'cool',
message : 'Would you like to enable the Cool feature?'
}]);
}

writing() {
this.log('cool feature', this.answers.cool); // user answer `cool` used
}
};

记住用户首选项

用户每次运行生成器时都可以对某些问题给出相同的输入。对于这些问题,您可能想要记住用户之前回答的内容并将该答案用作新答案default

Yeoman通过向问题对象添加store属性来扩展Inquirer.js API 。此属性允许您指定将来应将用户提供的答案用作默认答案。这可以按如下方式完成:

1
2
3
4
5
6
this.prompt({
type : 'input',
name : 'username',
message : 'What\'s your GitHub username',
store : true
});

注意:提供默认值将阻止用户返回任何空答案。

如果您只想存储数据而不直接与提示相关联,请务必查看Yeoman存储文档

参数

参数直接从命令行传递:

1
yo webapp my-project

在这个例子中,my-project将是第一个参数。

要通知系统我们期望参数,我们使用该this.argument()方法。此方法接受name(String)和可选的选项哈希。

name随后的参数将作为:this.options[name]

options散列接受多个键值对:

  • desc 参数的描述
  • required布尔值是否是必需的
  • type String,Number,Array(也可以是接收原始字符串值并解析它的自定义函数)
  • default 此参数的默认值

必须在constructor方法内调用此方法。否则,当用户使用帮助选项调用您的生成器时,Yeoman将无法输出相关的帮助信息:例如yo webapp --help

这是一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
module.exports = class extends Generator {
// note: arguments and options should be defined in the constructor.
constructor(args, opts) {
super(args, opts);

// This makes `appname` a required argument.
this.argument('appname', { type: String, required: true });

// And you can then access it later; e.g.
this.log(this.options.appname);
}
};

类型的参数Array将包含传递给生成器的所有剩余参数。

选项

选项看起来很像参数,但它们被写为命令行标志。

1
yo webapp --coffee

要通知系统我们期望一个选项,我们使用该this.option()方法。此方法接受name(String)和可选的选项哈希。

该name值将用于在匹配键处检索选项this.options[name]

options hash(第二个参数)接受多个键值对:

  • desc 选项说明
  • alias 选项的简称
  • type 布尔值,字符串或数字(也可以是接收原始字符串值并解析它的自定义函数)
  • default 默认值
  • hide 布尔值是否隐藏帮助

这是一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
module.exports = class extends Generator {
// note: arguments and options should be defined in the constructor.
constructor(args, opts) {
super(args, opts);

// This method adds support for a `--coffee` flag
this.option('coffee');

// And you can then access it later; e.g.
this.scriptSuffix = (this.options.coffee ? ".coffee": ".js");
}
};

输出信息

输出信息由this.log模块处理。

您将使用的主要方法是this.log(例如this.log('Hey! Welcome to my awesome generator'))。它需要一个字符串并将其输出给用户; 基本上它console.log()在终端会话中使用时模仿。您可以像这样使用它:

1
2
3
4
5
module.exports = class extends Generator {
myAction() {
this.log('Something has gone wrong!');
}
};

您还可以在API文档中找到其他一些辅助方法。

Powered by Hexo and Hexo-theme-hiker

Copyright © 2013 - 2021 朝着牛逼的道路一路狂奔 All Rights Reserved.

访客数 : | 访问量 :