与用户交互

你的生成器将与最终用户进行大量交互。默认情况下,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 文档