在handlebars JS中是否有一种方法可以将逻辑操作符合并到标准handlebars. JS条件操作符中?就像这样:

{{#if section1 || section2}}
.. content
{{/if}}

我知道我可以编写自己的助手,但首先我想确保我没有重复工作。


当前回答

这里发布的所有答案的一个问题是,它们不能与绑定属性一起工作,即当涉及的属性发生变化时,if条件不会重新计算。下面是稍微高级一点的支持绑定的帮助器版本。它使用来自Ember源的bind函数,该函数也用于实现正常的Ember #if helper。

与右边的常数相比,这一项在左边被限制为一个单一的边界性质,我认为这对于大多数实际目的来说已经足够好了。如果需要比简单比较更高级的东西,那么最好开始声明一些计算属性,并使用普通的# If helper。

Ember.Handlebars.registerHelper('ifeq', function(a, b, options) {
  return Ember.Handlebars.bind.call(options.contexts[0], a, options, true, function(result) {
    return result === b;
  });
});

你可以这样使用它:

{{#ifeq obj.some.property "something"}}
  They are equal!
{{/ifeq}}

其他回答

这里我们有多个逻辑&&和||(和或)的香草手柄:

Handlebars.registerHelper("and",function() {
    var args = Array.prototype.slice.call(arguments);
    var options = args[args.length-1];

    for(var i=0; i<args.length-1; i++){
        if( !args[i] ){
            return options.inverse(this);
        }
    }

    return options.fn(this);
});


Handlebars.registerHelper("or",function() {
    var args = Array.prototype.slice.call(arguments);
    var options = args[args.length-1];

    for(var i=0; i<args.length-1; i++){
        if( args[i] ){
            return options.fn(this);
        }
    }

    return options.inverse(this);
}

// Results
// {{#and foo bar sally bob}} yup {{else}} nope {{/and}} // yup
// {{#or foo bar "" sally bob}} yup {{else}} nope {{/or}} // yup

// {{#and foo bar "" sally bob}} yup {{else}} nope {{/and}} // nope
// {{#or "" "" "" "" ""}} yup {{else}} nope {{/or}} // nope

不太确定使用“and”和“or”是否“安全”…也许可以改成“op_and”和“op_or”之类的?

我可以理解为什么你想要创建一个helper的情况下,你有大量不同的比较在你的模板中执行,但相对较少的比较(甚至是一个,这是把我带到这个页面的第一个位置),它可能只是更容易定义一个新的句柄变量在你的视图渲染函数调用,如:

传递到渲染手柄:

var context= {
    'section1' : section1,
    'section2' : section2,
    'section1or2' : (section1)||(section2)
};

然后在handlebars模板中:

{{#if section1or2}}
    .. content
{{/if}}

我提到这一点是为了简单起见,也因为这是一个可能快速且有帮助的答案,同时仍然符合Handlebars的无逻辑性质。

更进一步的解决方案。这将添加比较操作符。

Handlebars.registerHelper('ifCond', function (v1, operator, v2, options) {

    switch (operator) {
        case '==':
            return (v1 == v2) ? options.fn(this) : options.inverse(this);
        case '===':
            return (v1 === v2) ? options.fn(this) : options.inverse(this);
        case '!=':
            return (v1 != v2) ? options.fn(this) : options.inverse(this);
        case '!==':
            return (v1 !== v2) ? options.fn(this) : options.inverse(this);
        case '<':
            return (v1 < v2) ? options.fn(this) : options.inverse(this);
        case '<=':
            return (v1 <= v2) ? options.fn(this) : options.inverse(this);
        case '>':
            return (v1 > v2) ? options.fn(this) : options.inverse(this);
        case '>=':
            return (v1 >= v2) ? options.fn(this) : options.inverse(this);
        case '&&':
            return (v1 && v2) ? options.fn(this) : options.inverse(this);
        case '||':
            return (v1 || v2) ? options.fn(this) : options.inverse(this);
        default:
            return options.inverse(this);
    }
});

在模板中使用它,就像这样:

{{#ifCond var1 '==' var2}}

脚本版本

Handlebars.registerHelper 'ifCond', (v1, operator, v2, options) ->
    switch operator
        when '==', '===', 'is'
            return if v1 is v2 then options.fn this else options.inverse this
        when '!=', '!=='
            return if v1 != v2 then options.fn this else options.inverse this
        when '<'
            return if v1 < v2 then options.fn this else options.inverse this
        when '<='
            return if v1 <= v2 then options.fn this else options.inverse this
        when '>'
            return if v1 > v2 then options.fn this else options.inverse this
        when '>='
            return if v1 >= v2 then options.fn this else options.inverse this
        when '&&', 'and'
            return if v1 and v2 then options.fn this else options.inverse this
        when '||', 'or'
            return if v1 or v2 then options.fn this else options.inverse this
        else
            return options.inverse this

下面是我在ember 1.10和ember-cli 2.0中使用的方法。

// app/helpers/js-x.js
export default Ember.HTMLBars.makeBoundHelper(function (params) {
  var paramNames = params.slice(1).map(function(val, idx) { return "p" + idx; });
  var func = Function.apply(this, paramNames.concat("return " + params[0] + ";"))
  return func.apply(params[1] === undefined ? this : params[1], params.slice(1));
});

然后你可以像这样在你的模板中使用它:

// used as sub-expression
{{#each item in model}}
  {{#if (js-x "this.section1 || this.section2" item)}}
  {{/if}}
{{/each}}

// used normally
{{js-x "p0 || p1" model.name model.offer.name}}

表达式的参数被传递为p0,p1,p2等,p0也可以被引用为this。

这里有一个我使用的块助手的链接:比较块助手。它支持所有标准操作符,并允许您编写如下所示的代码。真的很方便。

{{#compare Database.Tables.Count ">" 5}}
There are more than 5 tables
{{/compare}}