handlebars JS中是否可以将逻辑运算符合并到标准handlebars.js条件运算符中?像这样:
{{#if section1 || section2}}
.. content
{{/if}}
我知道我可以编写自己的帮助程序,但是首先我想确保自己不会重新发明轮子。
handlebars JS中是否可以将逻辑运算符合并到标准handlebars.js条件运算符中?像这样:
{{#if section1 || section2}}
.. content
{{/if}}
我知道我可以编写自己的帮助程序,但是首先我想确保自己不会重新发明轮子。
在Ember.js中,可以在if阻止帮助程序中使用内联if帮助程序。它可以代替||
逻辑运算符,例如:
{{#if (if firstCondition firstCondition secondCondition)}}
(firstCondition || (or) secondCondition) === true
{{/if}}
按照这两个指南,让用户定义自定义绑定if语句和自定义绑定帮助器,我能够在stackoverflow上的这篇文章中调整我的共享视图,以使用它代替标准的#如果声明。这不仅比在其中扔一个#if更安全。
该要旨中的自定义绑定帮手非常出色。
<li>
<a href="{{unbound view.varProductSocialBlog}}">
{{#if-equal view.showDiv "true"}}<div>{{/if-equal}}<i class="fa fa-rss-square"></i>{{#if-equal view.showDiv "true"}}</div>{{/if-equal}}
{{#if-equal view.showTitle "true"}}Blog{{/if-equal}}
</a>
</li>
我正在使用ember cli项目来构建我的ember应用程序。
撰写本文时的当前设置:
DEBUG: -------------------------------
DEBUG: Ember : 1.5.1
DEBUG: Ember Data : 1.0.0-beta.7+canary.b45e23ba
DEBUG: Handlebars : 1.3.0
DEBUG: jQuery : 2.1.1
DEBUG: -------------------------------
在这里,我们有用于多个逻辑&&和||的香草车把。(和):
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”之类的东西?
对于那些在比较对象属性方面遇到问题的人,可以在助手内部添加此解决方案
我找到了一个由CoffeeScript制作的npm软件包,其中有许多令人难以置信的有用的辅助工具。查看以下URL中的文档:
https://npmjs.org/package/handlebars-helpers
您可以执行以下wget http://registry.npmjs.org/handlebars-helpers/-/handlebars-helpers-0.2.6.tgz
操作下载它们并查看软件包的内容。
您将能够执行类似{{#is number 5}}
或{{formatDate date "%m/%d/%Y"}}
通过运行以下命令来安装Ember Truth Helpers插件
余烬安装ember-truth-helpers
您可以开始使用大多数逻辑运算符(eq,not-eq,not和and,gt,gte,lt,lte,xor)。
{{#if (or section1 section2)}}
...content
{{/if}}
您甚至可以包含子表达式以进一步扩展,
{{#if (or (eq section1 "section1") (eq section2 "section2") ) }}
...content
{{/if}}
与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" numbretwo}}
do something
{{else}}
do something else
{{/compare}}
我建议将对象移出该函数,以获得更好的性能,但否则,您可以添加所需的任何比较函数,包括“ and”和“ or”。
不幸的是,这些解决方案都不能解决“ OR”运算符“ cond1 || cond2”的问题。
使用“ ^”(或)并检查cond2是否为true
{{#if cond1}}采取行动{{^}} {{#if cond2}}采取行动{{/ if}} {{/ if}}
违反了DRY规则。那么为什么不使用partial来减少混乱
{{#if cond1}}
{{> subTemplate}}
{{^}}
{{#if cond2}}
{{> subTemplate}}
{{/if}}
{{/if}}
这是我使用的块帮助器的链接: 比较块帮助器。它支持所有标准运算符,并允许您编写如下所示的代码。真的很方便。
{{#compare Database.Tables.Count ">" 5}}
There are more than 5 tables
{{/compare}}
改进的解决方案,基本上可以与任何二进制运算符一起使用(至少数字,字符串不能与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);
}
});
车把支持嵌套操作。如果我们将逻辑编写得有些不同,这将提供很大的灵活性(和更简洁的代码)。
{{#if (or section1 section2)}}
.. content
{{/if}}
实际上,我们可以添加各种逻辑:
{{#if (or
(eq section1 "foo")
(ne section2 "bar"))}}
.. content
{{/if}}
只需注册这些助手:
Handlebars.registerHelper({
eq: function (v1, v2) {
return v1 === v2;
},
ne: function (v1, v2) {
return v1 !== v2;
},
lt: function (v1, v2) {
return v1 < v2;
},
gt: function (v1, v2) {
return v1 > v2;
},
lte: function (v1, v2) {
return v1 <= v2;
},
gte: function (v1, v2) {
return v1 >= v2;
},
and: function () {
return Array.prototype.slice.call(arguments).every(Boolean);
},
or: function () {
return Array.prototype.slice.call(arguments, 0, -1).some(Boolean);
}
});
这是我用于ember 1.10和ember-cli 2.0的方法。
然后,您可以在模板中使用它,如下所示:
这里的参数来表达的传递为
p0
,p1
,p2
等,并p0
还可以作为参考this
。