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

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

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


当前回答

句柄支持嵌套操作。如果我们编写的逻辑稍有不同,这就提供了很大的灵活性(和更干净的代码)。

{{#if (or section1 section2)}}
.. content
{{/if}}

事实上,我们可以添加各种逻辑:

{{#if (or 
        (eq section1 "foo")
        (ne section2 "bar"))}}
.. content
{{/if}}

只需注册这些helper:

Handlebars.registerHelper({
    eq: (v1, v2) => v1 === v2,
    ne: (v1, v2) => v1 !== v2,
    lt: (v1, v2) => v1 < v2,
    gt: (v1, v2) => v1 > v2,
    lte: (v1, v2) => v1 <= v2,
    gte: (v1, v2) => v1 >= v2,
    and() {
        return Array.prototype.every.call(arguments, Boolean);
    },
    or() {
        return Array.prototype.slice.call(arguments, 0, -1).some(Boolean);
    }
});

其他回答

改进的解决方案,基本上适用于任何二进制操作符(至少数字,字符串不适用于eval,如果使用用户输入的非定义操作符,请注意可能的脚本注入):

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 eval(""+v1+operator+v2)?options.fn(this):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。

在Ember.js中,你可以在if块helper中使用内联if helper。它可以替换||逻辑运算符,例如:

{{#if (if firstCondition firstCondition secondCondition)}}
  (firstCondition || (or) secondCondition) === true
{{/if}}

您可以使用以下代码:

{{#if selection1}}
    doSomething1
{{else}}
   {{#if selection2}}
       doSomething2
   {{/if}}
{{/if}}

另一种替代方法是在#if中使用函数名。#if将检测参数是否为函数,如果是,则调用它并使用其返回值进行真实性检查。下面的myFunction得到当前的上下文。

{{#if myFunction}}
  I'm Happy!
{{/if}}