Yeoman:使用用户提供的参数调用子生成器 [英] Yeoman: Call Sub-Generator With User-Supplied Arguments

查看:27
本文介绍了Yeoman:使用用户提供的参数调用子生成器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm writing my first Yeoman generator, which prompts the user for various inputs and conditionally creates files based on their responses. I need to be able to call a subroutine (could be a Yeoman sub-generator) based on user input, and pass arguments to it.

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

The reason I want to use named functions (which are not automatically run) is that sometimes the user's response should invoke a number of functions combined, and sometimes the function should be run alone.

我尝试过的:

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

I figured sub-generators were the way to go, since I'm creating sets of files only if the user requests them. But I'm having trouble calling them conditionally and passing them the user-supplied input. I've tried using hookFor, but I get the assertion error: hookFor must be used within the constructor only. (Because I don't want it to be run by default, I'm calling the sub-generator from my this.prompt(prompts, function (props)).

问题:

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

How do I call a routine only if the user requests it (via a prompt), and pass that routine some user-supplied information?

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

If you're kind enough to answer, please don't assume that I've tried something obvious ;-).

推荐答案

假设您有一个生成器 generator-blog (BlogGenerator) 和两个子生成器(博客服务器和博客客户端):

Let's consider you have a generator generator-blog (BlogGenerator) with two sub generators (blog-server and blog-client):

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

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

So when you run yo blog you what to ask the user for some options and run (optionally) sub generators, right?

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

To run a subgenerator you need to call this.invoke("generator_namespace", {options: {}}). The second argument we passed can have options field - it's options object which will be passed to the generator.

在 app\index.js 中:

In 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}});
  }
};

在 client\index.js 中:

In client\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 方法的样子:

UPDATE 2015-12-21:
Using invoke is deprecated now and should be replaced with composeWith. But it's not as easy as it could be. The main difference between invoke and composeWith is that now you have no ability to control subgenerators. You could only declare using them.
Here's how main method from above should look like:

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.

Also I removed replaced yeoman.generators.Base with yeoman.Base.

这篇关于Yeoman:使用用户提供的参数调用子生成器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆