與使用者互動

產生器將會頻繁地與最終使用者互動。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佇列 向使用者索取意見回饋。

在後續階段使用使用者解答

一個非常常見的場景是在後續階段使用使用者解答,例如 寫入佇列 中。這可以透過將它們新增至 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
  }
};

記住使用者偏好設定

使用者可能會在每次執行產生器時,針對某些問題給出相同的輸入。對於這些問題,您可能會想要記住使用者之前回答的內容,並將該解答用作新的 預設值

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] 的形式提供。

選項雜湊接受多組關鍵字值對。

  • 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 型別的引數將包含所有傳遞至產生器的剩餘引數。

選項

選項看起來很像引數,不過它們寫成指令列「flag」。

yo webapp --coffee

若要通知系統我們期望得到一個選項,我們使用 this.option() 方法。此方法接受一個 name(字串)以及一個選項雜湊(選用)。

name 值會用來在符合鍵 this.options[name] 中擷取選項。

選項雜湊(第二個引數)接受多組關鍵字值對。

  • 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('嘿!歡迎來到我超棒的產生器'))。它會接收一個字串,並將其輸出給使用者;基本上,當在終端機工作階段中使用時,它會模擬 console.log()。使用方法如下

module.exports = class extends Generator {
  myAction() {
    this.log("Something has gone wrong!");
  }
};

你還可以在 API 文件 中找到一些其他輔助方法。