如何使用每个子句中的路径作为 handlebars.js 中的辅助参数

How to use path from within each clause as helper argument in handlebars.js

我有以下场景

    {{#each (concatArray setra.features lion.features)}}
    <tr>
        <td><h4 class="ui header">{{this}}</h4></td>
        <td>{{#if contains ../setra.features this}}YES{{/if}}</td>
        <td>{{#if contains ../lion.features this}}YES{{/if}}</td>
    </tr>
    {{/each}}

其中 concatArray 是一个辅助函数,returns 一个字符串数组,它是所有特征的串联。

如何正确编写上面的语句?

在 each 子句中,我可以通过转义 each 上下文来访问 setra.features 和 lion.features:

{{#each (concatArray setra.features lion.features)}}
{{../setra.features}} <!-- is accessible -->
{{/each}}

但是一旦我想在我的辅助函数 contains 中使用其中任何一个作为参数,它就会给我错误,具体取决于我尝试实现它的方式。上面的示例目前给我一个 "Cannot read property 'includeZero' of undefined" 错误,这似乎很可能是因为路径未正确评估。

辅助函数如下:

var contains = function(array, string){

    if(array && array.indexOf(string) > -1){ return true; }
    return false;
}

exports.contains = contains;

var concatArray = function(array1, array2){
    var newArray = array1;

    array2.forEach(function(element){
        if(newArray.indexOf(element) < 0){
            newArray.push(element);
        }
    });

    return newArray;
}

exports.concatArray = concatArray;

第一个问题是 #if 之后的所有项目都被视为 Handlebars #if block helper 的单独参数。 #if 需要一个参数,一个布尔表达式。

车把支持 subexpressions。来自文档:

Handlebars offers support for subexpressions, which allows you to invoke multiple helpers within a single mustache, and pass in the results of inner helper invocations as arguments to outer helpers. Subexpressions are delimited by parentheses.

按照这些说明,模板中的 #if 块必须更新为以下内容:

<td>{{#if (contains ../setra.features this)}}YES{{/if}}</td>
<td>{{#if (contains ../lion.features this)}}YES{{/if}}</td>

运行 代码现在不应抛出 "includeZero" 错误。但是,仍然存在问题。似乎 contains 助手 always returns true 当传递 ../setra.features.

这是因为 concatArray 助手正在更改 setra.features 的值。事实上,“concatArray”修改了它的第一个数组参数,使其值成为所有 "concatenated" 个数组的结果。 (请注意,您的助手并不是严格意义上的 "concatentation",因为它还会删除重复元素。)

要解决此问题,我们需要 concatArray 修改其第一个数组参数的 copy,而不是修改第一个数组参数本身。有a few ways to do this, but I will use JavaScript's Array.prototype.concat:

//var newArray = array1;
var newArray = [].concat(array1);

最后,为了简洁起见,我会稍微重构一下您的 contains 助手。我认为以下更漂亮:

var contains = function (array, string) {
    return (Array.isArray(array) && array.indexOf(string) > -1);
}