【问题标题】:Grunt - resolving non-string (eg array) templatesGrunt - 解析非字符串(例如数组)模板
【发布时间】:2013-04-12 20:34:59
【问题描述】:

假设我的 grunt 配置中有一个变量,其中一个数组作为值。一个真实的例子是来自grunt-regarde 插件的grunt.regarde.changed,它列出了所有已更改的文件。

我想使用模板解析该数组,以便(在这种情况下)复制更改的文件:

  copy: {
    staticWeb: {
      src: '<%= grunt.regarde.changed %>',
      dest: 'someDir'
    },

src 在这种情况下得到的是单个逗号分隔的字符串而不是数组。 Grunt 的文件处理器不解析字符串,所以找不到 src 文件。

我无法删除模板周围的单引号,因为它是无效的 javascript。

那么如何将 grunt.regarde.changed 数组传递给 src 变量?

【问题讨论】:

  • 在未来,我希望 grunt 模板能够原生处理非字符串值。不过,就目前而言,oligofren's answer 是我们最好的选择。它应该是公认的答案。

标签: javascript gruntjs


【解决方案1】:

一旦你知道怎么做,问题就很容易解决,只需要几行代码,但我花了很长时间从 Grunt 源代码中挖掘所有相关信息以了解该怎么做,所以在我带你穿越背景时,请耐心等待......


获取配置对象的属性的一般方法很简单:

<%= some.property %> // fetches grunt.config.get('some.property')

这适用于在grunt.config 对象上设置的所有属性,其中(当然)包括传递给grunt.initConfig() 的配置。这就是为什么您可以直接引用其他任务变量的原因,例如在&lt;%= concat.typescriptfiles.dest %&gt; 中,因为配置对象中的所有属性都在模板自己的范围内。

从技术上讲,当 (LoDash) 模板与 options 对象(如果已定义)或 grunt.config 对象一起传递给模板处理器(LoDash'template 函数)时,就会发生这种扩展。

因此,这适用于已在配置本身中设置的值,或者通过使用通过 grunt.config.set() 动态分配的值。请参阅API docs 了解更多信息。

访问配置对象上不可用的值的方式不同。似乎由于某种原因我不太确定,所有其他值总是以字符串结尾。无论您是直接访问它们还是通过方法调用,都会发生这种情况。例如,尝试通过 grunt.config.get() 访问配置中的数组会得到一个字符串。

保留文件顺序问题的解决方法

接受的答案在某种程度上是有效的,但由于使用通配符语法,它将被glob() 模块解析不保留文件顺序。这对我的构建来说是一个禁忌。

如果您要使用的数组在配置对象上不可用,一种解决方法是通过中间任务将其添加到配置中。像下面这样的东西应该可以工作:

// This variable will be used twice to demonstrate the difference
// between directly setting an attribute on the grunt object
// and using the setter method on the grunt.config object
var myFiles = ['c/file1.txt', 'a/file2.txt', 'b/file3.txt']
module.exports = function(grunt){

    grunt.initConfig({

        debug : {
            using_attribute: {
                src : '<%= grunt.value_as_attribute %>' // will be a string
            },
            using_task: {
                src : '<%= value_by_setter %>' // will be an array
            },
            no_task_direct_setter: {
                src : '<%= value_by_setter_early %>' // will be an array
            }
        }        
    });

    grunt.registerTask('myValSetter', function() {
        grunt.config.set('value_by_setter', myFiles );
    });

    // a task that will report information on our set values
    grunt.registerMultiTask('debug', function(){
        grunt.log.writeln('data.src: ', this.data.src);
        grunt.log.writeln('type: ', Array.isArray(this.data.src)? "Array" : typeof this.data.src);
    });

    grunt.value_as_attribute = myFiles;

    grunt.config.set('value_by_setter_early', myFiles );

    grunt.registerTask('default',['myValSetter', 'debug']);
}

这将输出

$ grunt
Running "myValSetter" task

Running "debug:using_attribute" (debug) task
data.src:  c/file1.txt,a/file2.txt,b/file3.txt
type:  string

Running "debug:using_task" (debug) task
data.src:  [ 'c/file1.txt', 'a/file2.txt', 'b/file3.txt' ]
type:  Array

Running "debug:no_task_direct_setter" (debug) task
data.src:  [ 'c/file1.txt', 'a/file2.txt', 'b/file3.txt' ]
type:  Array

Done, without errors.

这个例子只是为了说明这个概念,但你应该能够很容易地为你的实例定制它:)

【讨论】:

  • 这太棒了。谢谢你。我为实现所做的一项更改是使用 grunt.config.set 创建一个名为 grunt.values 的单一 grunt “全局”,以包含在配置中多次使用的所有非字符串值。例如grunt.config.set('values', { a:[1,2], b:[2,3], etc:[3,4] })。另外,我认为不需要创建其他grunt 属性,如您的示例中所示grunt.somevalue。直接用grunt.config.set“注册”非字符串值似乎就足够了。
  • 太好了,有人利用了它——我记得我用了一整夜的黑客攻击,包括阅读所有相关的 Grunt 源代码以了解幕后发生的事情!您对grunt.somevalue 的看法是正确的。我现在用答案中的普通变量替换了它。
  • 哦,现在我想起来了。我用它来展示直接读取设置属性值和使用 grunt.config.set 之间的区别。我必须恢复我的编辑,否则 cmets 没有意义。 //src : '' // 将是一个字符串
  • 我已经清理了答案,添加了一些任务,并重命名了任务,以便更清楚发生了什么以及为什么发生。
【解决方案2】:

我遇到了和你完全相同的问题,通过用大括号括住你的模板来解决它。

所以这是你的代码,修改后

copy: {
  staticWeb: {
    src: '{<%= grunt.regarde.changed %>}', // added curly brackets
    dest: 'someDir'
  }
}

它将src 输出为{source1,source2,source3},这与使用数组相同。 (见Globbing Patterns in Grunt Documentation)

【讨论】:

【解决方案3】:
// assuming that regarde is a grunt plugin (haven't used—link is broken)

copy: {
  staticWeb: {
    src: '<% regarde.changed %>',
    dest: 'someDir'
  }
}

http://gruntjs.com/api/grunt.config#grunt.config.getraw

#ezpz

【讨论】:

    【解决方案4】:

    你试过了吗:

    copy: {
      staticWeb: {
        src: '<%= grunt.regarde.changed.split(",") %>',
        dest: 'someDir'
      }
    }
    

    【讨论】:

    • 你试过了吗?它不适用于 Grunt v0.4.5,它目前是最新的稳定版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-11
    • 2013-07-09
    • 2013-08-28
    • 1970-01-01
    • 2020-02-24
    • 2022-01-04
    • 2017-03-01
    相关资源
    最近更新 更多