在handlebars JS中是否有一种方法可以将逻辑操作符合并到标准handlebars. JS条件操作符中?就像这样:
{{#if section1 || section2}}
.. content
{{/if}}
我知道我可以编写自己的助手,但首先我想确保我没有重复工作。
在handlebars JS中是否有一种方法可以将逻辑操作符合并到标准handlebars. JS条件操作符中?就像这样:
{{#if section1 || section2}}
.. content
{{/if}}
我知道我可以编写自己的助手,但首先我想确保我没有重复工作。
当前回答
您可以使用以下代码:
{{#if selection1}}
doSomething1
{{else}}
{{#if selection2}}
doSomething2
{{/if}}
{{/if}}
其他回答
改进的解决方案,基本上适用于任何二进制操作符(至少数字,字符串不适用于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);
}
});
与Jim的答案类似,但我们也可以使用一点创造力,这样做:
Handlebars.registerHelper( "compare", function( v1, op, v2, options ) {
var c = {
"eq": function( v1, v2 ) {
return v1 == v2;
},
"neq": function( v1, v2 ) {
return v1 != v2;
},
...
}
if( Object.prototype.hasOwnProperty.call( c, op ) ) {
return c[ op ].call( this, v1, v2 ) ? options.fn( this ) : options.inverse( this );
}
return options.inverse( this );
} );
然后使用它,我们得到如下内容:
{{#compare numberone "eq" numbertwo}}
do something
{{else}}
do something else
{{/compare}}
我建议将对象移出函数以获得更好的性能,否则您可以添加任何您想要的比较函数,包括“and”和“or”。
句柄支持嵌套操作。如果我们编写的逻辑稍有不同,这就提供了很大的灵活性(和更干净的代码)。
{{#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);
}
});
下面是我在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。
AND/OR的正确解
Handlebars.registerHelper('and', function () {
// Get function args and remove last one (function name)
return Array.prototype.slice.call(arguments, 0, arguments.length - 1).every(Boolean);
});
Handlebars.registerHelper('or', function () {
// Get function args and remove last one (function name)
return Array.prototype.slice.call(arguments, 0, arguments.length - 1).some(Boolean);
});
然后按如下方式调用
{{#if (or (eq questionType 'STARTTIME') (eq questionType 'ENDTIME') (..) ) }}
顺便说一句:注意,这里给出的解决方案是不正确的,他没有减去最后一个参数,也就是函数名。 https://stackoverflow.com/a/31632215/1005607
他最初的AND/OR是基于完整的论证列表
and: function () {
return Array.prototype.slice.call(arguments).every(Boolean);
},
or: function () {
return Array.prototype.slice.call(arguments).some(Boolean);
}
有人能改一下答案吗?我刚刚浪费了一个小时试图修正一个由86人推荐的答案。修复方法是过滤掉函数名的最后一个参数。Array.prototype.slice。调用(arguments, 0, arguments。长度- 1)