你的生成器将与最终用户进行大量交互。默认情况下,Yeoman 在终端上运行,但它也支持不同工具可以提供的自定义用户界面。例如,没有任何东西可以阻止 Yeoman 生成器在图形工具(如编辑器或独立应用程序)中运行。
为了允许这种灵活性,Yeoman 提供了一组用户界面元素抽象。作为作者,你只负责在与最终用户交互时使用这些抽象。使用其他方法可能会阻止你的生成器在不同的 Yeoman 工具中正确运行。
例如,切勿使用 console.log()
或 process.stdout.write()
来输出内容非常重要。使用它们会隐藏非终端用户看不到的输出。相反,始终依赖 UI 通用 this.log()
方法,其中 this
是当前生成器的上下文。
用户交互
提示
提示是生成器与用户交互的主要方式。提示模块由 Inquirer.js 提供,你应该参考 其 API 以获取可用提示选项的列表。
prompt
方法是异步的,并返回一个 promise。你需要从你的任务中返回 promise,以便在运行下一个任务之前等待其完成。(了解有关异步任务的更多信息)
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
队列 来请求用户的反馈。
在以后阶段使用用户答案
一个非常常见的场景是在以后的阶段使用用户答案,例如在 writing
队列 中。这可以通过将它们添加到 this
上下文中轻松实现
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。此属性允许你指定用户提供的答案应在将来用作默认答案。这可以通过以下方式完成
this.prompt({
type: "input",
name: "username",
message: "What's your GitHub username",
store: true
});
注意:提供默认值将阻止用户返回任何空答案。
如果你只想存储数据而不直接与提示绑定,请确保查看 Yeoman 存储文档。
参数
参数直接从命令行传递
yo webapp my-project
在此示例中,my-project
将是第一个参数。
为了通知系统我们期望一个参数,我们使用 this.argument()
方法。此方法接受一个 name
(字符串)和一个可选的选项哈希。
name
参数随后将可用为:this.options[name]
。
options 哈希接受多个键值对
desc
参数描述required
布尔值,指示是否必需type
字符串、数字、数组(也可以是接收原始字符串值并对其进行解析的自定义函数)default
此参数的默认值
此方法必须在 constructor
方法中调用。否则,当用户使用帮助选项调用你的生成器时,Yeoman 将无法输出相关的帮助信息:例如 yo webapp --help
。
这是一个示例
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
的参数将包含传递给生成器的所有剩余参数。
选项
选项看起来很像参数,但它们被写成命令行标志。
yo webapp --coffee
为了通知系统我们期望一个选项,我们使用 this.option()
方法。此方法接受一个 name
(字符串)和一个可选的选项哈希。
name
值将用于在匹配的键 this.options[name]
处检索选项。
options 哈希(第二个参数)接受多个键值对
desc
选项描述alias
选项的简称type
布尔值、字符串或数字(也可以是接收原始字符串值并对其进行解析的自定义函数)default
默认值hide
布尔值,指示是否从帮助中隐藏
这是一个示例
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()
。你可以像这样使用它
module.exports = class extends Generator {
myAction() {
this.log("Something has gone wrong!");
}
};
你还可以找到一些其他辅助方法 API 文档。