javascript - Yeoman:使用用户提供的参数调用子生成器

标签 javascript yeoman yeoman-generator

我正在编写我的第一个 Yeoman 生成器,它会提示用户进行各种输入并根据他们的响应有条件地创建文件。我需要能够根据用户输入调用子例程(可以是 Yeoman 子生成器),并将参数传递给它。

我想使用命名函数(不会自动运行)的原因是有时用户的响应应该调用组合的多个函数,而有时函数应该单独运行。

我尝试过的:

我认为子生成器是可行的方法,因为只有在用户请求时我才创建文件集。但是我无法有条件地调用它们并将用户提供的输入传递给它们。我已经尝试使用 hookFor,但我收到断言错误:hookFor 必须仅在构造函数中使用。 (因为我不希望它默认运行,所以我从我的 this.prompt(prompts, function (props)) 调用子生成器。

问题:

如何仅在用户请求(通过提示)时调用例程,并向该例程传递一些用户提供的信息?

如果您愿意回答,请不要假设我已经尝试了一些显而易见的事情 ;-)。

最佳答案

假设您有一个生成器 generator-blog (BlogGenerator) 和两个子生成器(blog-server 和 blog-client):

app\index.js
client\index.js
server\index.js

因此,当您运行 yo blog 时,您应该向用户询问一些选项并运行(可选)子生成器,对吧?

要运行子生成器,您需要调用 this.invoke("generator_namespace", {options: {}})。 我们传递的第二个参数可以有 options 字段——它是将传递给生成器的选项对象。

在 app\index.js 中:

BlogGenerator.prototype.askFor = function askFor() {
  var cb = this.async();

  // have Yeoman greet the user.
  console.log(this.yeoman);

  var prompts = [{
    name: 'appName',
    message: 'Enter your app name',
    default: 'MyBlog'
  }, {
    type: 'confirm',
    name: 'createServer',
    message: 'Would you like to create server project?',
    default: true
  }, {
    type: 'confirm',
    name: 'createClient',
    message: 'Whould you like to create client project?',
    default: true
  }];

  this.prompt(prompts, function (props) {
    this.appName = props.appName;
    this.createServer = props.createServer;
    this.createClient = props.createClient;

    cb();
  }.bind(this));
}

BlogGenerator.prototype.main = function app() {
  if (this.createClient) {
    // Here: we'are calling the nested generator (via 'invoke' with options)
    this.invoke("blog:client", {options: {nested: true, appName: this.appName}});
  }
  if (this.createServer) {
    this.invoke("blog:server", {options: {nested: true, appName: this.appName}});
  }
};

在客户端\index.js中:

var BlogGenerator = module.exports = function BlogGenerator(args, options, config) {
  var that = this;
  yeoman.Base.apply(this, arguments);
  // in this.options we have the object passed to 'invoke' in app/index.js:
  this.appName = that.options.appName;
  this.nested  = that.options.nested;
};

BlogGenerator .prototype.askFor = function askFor() {
  var cb = this.async();

  if (!this.options.nested) {
    console.log(this.yeoman);
  }
}

2015 年 12 月 21 日更新:
使用 invoke 现已弃用,应替换为 composeWith。但这并不像想象的那么容易。 invokecomposeWith 之间的主要区别在于,现在您无法控制子生成器。您只能声明使用它们。
上面的 main 方法应该是这样的:

BlogGenerator.prototype.main = function app() {
  if (this.createClient) {
    this.composeWith("blog:client", { 
        options: { 
          nested: true, 
          appName: this.appName
        } 
      }, {
        local: require.resolve("./../client")
      });
  }
  if (this.createServer) {
    this.composeWith("blog:server", { 
        options: { 
          nested: true, 
          appName: this.appName
        } 
      }, {
        local: require.resolve("./../server")
      });
  }
};

我还删除了用 yeoman.Base 替换的 yeoman.generators.Base

关于javascript - Yeoman:使用用户提供的参数调用子生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20721060/

相关文章:

javascript - 绕过 URL 编码(客户端)执行 XSS

Javascript 传递变量在 Ajax 中不起作用

concatenation - Yeoman & RequireJS 使用动态生成的 HTML 构建?

npm - 创建 Yeoman 生成器后, `npm install` 是否应该需要 10 分钟才能运行,还是我做错了什么?

javascript - Nodejs - Spotify API 刷新 token

Javascript 的 SetTimeout、SetInterval 和 ClearInterval 在 c# 中的等价物

angularjs - 在 AngularJS 应用程序中使用 node_modules

node.js - Socket.io回调函数参数混淆

javascript - 如何为自定义 yeoman 生成器文件设置目标路径?

yeoman - 添加什么 <style type ="text/css">body { display : none ! important }</style>