<p>Url: {{x "'hi' + name + ', ' + window.location.href + ' <---- this is your href,' + ' your Age is:' + parseInt(this.age, 10)"}}</p>
输出:
<p>Url: hi Sam, http://example.com <---- this is your href, your Age is: 20</p>
JavaScript:
这看起来有点大,因为为了清晰起见,我扩展了语法并对几乎每一行进行了评论
Handlebars.registerHelper("x", function(expression, options) {
var result;
// you can change the context, or merge it with options.data, options.hash
var context = this;
// yup, i use 'with' here to expose the context's properties as block variables
// you don't need to do {{x 'this.age + 2'}}
// but you can also do {{x 'age + 2'}}
// HOWEVER including an UNINITIALIZED var in a expression will return undefined as the result.
with(context) {
result = (function() {
try {
return eval(expression);
} catch (e) {
console.warn('•Expression: {{x \'' + expression + '\'}}\n•JS-Error: ', e, '\n•Context: ', context);
}
}).call(context); // to make eval's lexical this=context
}
return result;
});
Handlebars.registerHelper("xif", function(expression, options) {
return Handlebars.helpers["x"].apply(this, [expression, options]) ? options.fn(this) : options.inverse(this);
});
var data = [{
firstName: 'Joan',
age: '21',
email: 'joan@aaa.bbb'
}, {
firstName: 'Sam',
age: '18',
email: 'sam@aaa.bbb'
}, {
firstName: 'Perter',
lastName: 'Smith',
age: '25',
email: 'joseph@aaa.bbb'
}];
var source = $("#template").html();
var template = Handlebars.compile(source);
$("#main").html(template(data));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.min.js"></script>
<script id="template" type="text/x-handlebars-template">
<div class="content">
{{#each this}}
<div class="person">
<h1>{{x "'Hi ' + firstName"}}, {{x 'lastName'}}</h1>
<div>{{x '"you were born in " + ((new Date()).getFullYear() - parseInt(this.age, 10)) '}}</div>
{{#xif 'parseInt(age) >= 21'}} login here:
<a href="http://foo.bar?email={{x 'encodeURIComponent(email)'}}">
http://foo.bar?email={{x 'encodeURIComponent(email)'}}
</a>
{{else}} Please go back when you grow up. {{/xif}}
</div>
{{/each}}
</div>
</script>
<div id="main"></div>
摩尔
如果你想访问上层范围,这个稍微不同,表达式是所有参数的JOIN,用法:说上下文数据如下所示:
// data
{name: 'Sam', age: '20', address: { city: 'yomomaz' } }
// in template
// notice how the expression wrap all the string with quotes, and even the variables
// as they will become strings by the time they hit the helper
// play with it, you will immediately see the errored expressions and figure it out
{{#with address}}
{{z '"hi " + "' ../this.name '" + " you live with " + "' city '"' }}
{{/with}}
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);
}
});
116
三元助手的又一个弯曲解决方案:
'?:' ( condition, first, second ) {
return condition ? first : second;
}
<span>{{?: fooExists 'found it' 'nope, sorry'}}</span>
或者一个简单的合并助手:
'??' ( first, second ) {
return first ? first : second;
}
<span>{{?? foo bar}}</span>
You can use the if helper to conditionally render a block. If its argument returns false, undefined, null, "", 0, or [], Handlebars will not render the block.
所以...
{{#if your_string.match "what_youre_looking_for"}}
String found :)
{{else}}
No match found :(
{{/if}}
UPDATE:
在所有浏览器上测试后, this doesn't work on Firefox . HandlebarsJS将其他参数传递给函数调用,这意味着当调用String.prototype.match时,第二个参数(即似乎正在传递匹配函数调用的regexp标志(如上文所示) . Firefox认为这是对String.prototype.match的弃用,因此中断 .
A workaround is to declare a new functional prototype for the String JS object ,并改为使用:
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);
});
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
6
有一种简单的方法可以在不编写辅助函数的情况下完成此操作......可以在模板中完成 .
{{#if cond1}}
{{#if con2}}
<div> and condition completed</div>
{{/if}}
{{else}}
<div> both conditions weren't true</div>
{{/if}}
编辑:反过来你可以这样做:
{{#if cond1}}
<div> or condition completed</div>
{{else}}
{{#if cond2}}
<div> or condition completed</div>
{{else}}
<div> neither of the conditions were true</div>
{{/if}}
{{/if}}
25 回答
在Ember.js中,你可以使用inline if helper in if block helper . 它可以替换
||
逻辑运算符,例如:您只需使用如下所示的逻辑运算符即可:
在结束之前,如果您可以编写业务逻辑
对于那些生活在边缘的人来说,把这个提升一个档次 .
gist :https://gist.github.com/akhoury/9118682 Demo :下面的代码段
Handlebars Helper:{} {} {{/ xif}}
一个帮助器,用于执行任何表达式的IF语句
EXPRESSION是一个正确转义的字符串
是的 NEED 正确转义字符串文字或只是替换单引号和双引号
您可以访问任何全局函数或属性,即
encodeURIComponent(property)
这个例子假设你把这个上下文传递给了你的把手
template( {name: 'Sam', age: '20' } )
,注意age
是一个string
,只是因为我可以在这篇文章的后面演示parseInt()
用法:
输出
JavaScript :(这取决于另一个助手 - 继续阅读)
Handlebars Helper:{}
执行javascript表达式的助手
EXPRESSION是一个正确转义的字符串
是的你 NEED 正确地转义字符串文字或只是替换单引号和双引号
您可以访问任何全局函数或属性,即
parseInt(property)
此示例假设您将此上下文传递给您的把手
template( {name: 'Sam', age: '20' } )
,age
是string
用于演示目的,它可以是任何东西..用法:
输出:
JavaScript:
这看起来有点大,因为为了清晰起见,我扩展了语法并对几乎每一行进行了评论
摩尔
如果你想访问上层范围,这个稍微不同,表达式是所有参数的JOIN,用法:说上下文数据如下所示:
Javascript:
改进的解决方案基本上适用于任何二元运算符(至少数字,字符串不能与eval一起使用,如果使用非定义的操作符和用户输入,请注意可能的脚本注入):
三元助手的又一个弯曲解决方案:
或者一个简单的合并助手:
由于这些字符在手柄标记中没有特殊含义,因此您可以将它们用于帮助程序名称 .
我找到了一个用CoffeeScript制作的npm包,它为Handlebars提供了许多令人难以置信的有用助手 . 请查看以下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"}}
之类的操作按照这两个指南a-way-to-let-users-define-custom-made-bound-if-statements和custom bound helpers,我能够在stackoverflow上的这篇文章中调整我的共享视图,以使用它而不是标准的#if语句 . 这应该比在那里扔#if更安全 .
该要点中的自定义绑定助手非常出色 .
我正在使用ember cli项目来构建我的ember应用程序 .
本帖时的当前设置:
这是我使用的块助手的链接:comparison block helper . 它支持所有标准运算符,并允许您编写如下所示的代码 . 这真的很方便 .
如果要检查多个条件,这是一个解决方案:
用法:
这里发布的所有答案的一个问题是,他们不需要支持绑定的帮助器的更高级版本 . 它使用Ember源中的bind函数,该函数也用于实现正常的Ember
#if
帮助器 .这个限制在左侧的单个绑定属性,与右侧的常量相比,我认为这对于大多数实际目的来说足够好 . 如果你需要比简单比较更先进的东西,那么也许最好开始声明一些计算属性并使用普通的
#if
助手 .你可以像这样使用它:
Handlebars支持嵌套操作 . 如果我们以稍微不同的方式编写逻辑,这会提供很多灵活性(以及更清晰的代码) .
实际上,我们可以添加各种逻辑:
只需注册这些助手:
刚刚从谷歌搜索来看这篇文章如何检查一个字符串是否等于另一个字符串 .
我在NodeJS服务器端使用HandlebarsJS,但我也使用HandlebarsJS的浏览器版本在前端使用相同的模板文件来解析它 . 这意味着如果我想要一个自定义帮助器,我必须在两个不同的位置定义它,或者为相关对象分配一个函数 - 太费力了!!
人们忘记的是某些对象具有可以在胡子模板中使用的继承函数 . 在字符串的情况下:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match
An Array containing the entire match result and any parentheses-captured matched results; null if there were no matches.
我们可以使用此方法返回匹配数组,如果未找到匹配项,则返回
null
. 这很完美,因为查看HandlebarsJS文档http://handlebarsjs.com/builtin_helpers.htmlYou can use the if helper to conditionally render a block. If its argument returns false, undefined, null, "", 0, or [], Handlebars will not render the block.
所以...
UPDATE:
在所有浏览器上测试后, this doesn't work on Firefox . HandlebarsJS将其他参数传递给函数调用,这意味着当调用String.prototype.match时,第二个参数(即似乎正在传递匹配函数调用的regexp标志(如上文所示) . Firefox认为这是对String.prototype.match的弃用,因此中断 .
A workaround is to declare a new functional prototype for the String JS object ,并改为使用:
确保包含此JS代码 before 您运行Handlebars.compile()函数,然后在您的模板中...
我可以理解为什么你想要在你的模板中进行大量不同比较的情况下创建一个帮助器,但对于相对较少的比较(甚至一个,这是我带到这个页面的原因)在第一个地方),在视图渲染函数调用中定义新的把手变量可能更容易,例如:
传递到渲染上的把手:
然后在你的车把模板中:
我为了简单起见提到了这一点,也因为它是一个快速而有用的答案,同时仍然符合Handlebars的无逻辑特性 .
运行以下命令安装Ember Truth Helpers addon
你可以开始使用大多数逻辑运算符(eq,not-eq,not,and,或gt,gte,lt,lte,xor) .
你甚至可以包括子表达式,以进一步,
如果您只想检查是否存在一个或另一个元素,则可以使用此自定义帮助程序
像这样
如果你还需要能够"or"来比较function return values我宁愿添加另一个返回所需结果的属性 .
毕竟模板应该是无逻辑的!
对于那些在比较对象属性时遇到问题的人,在帮助程序内添加此解决方案
Ember.js helper not properly recognizing a parameter
正确的AND / OR解决方案
然后打电话如下
顺便说一句:请注意,这里给出的解决方案是错误的,他没有减去最后一个参数,即函数名称 . https://stackoverflow.com/a/31632215/1005607
他的原始AND / OR基于完整的参数列表
有人可以改变这个答案吗?我只是浪费了一个小时试图解决86人推荐的答案 . 修复是 filter out the last 参数,这是函数名称 .
Array.prototype.slice.call(arguments, 0, arguments.length - 1)
进一步采取解决方案 . 这会添加比较运算符 .
在这样的模板中使用它:
咖啡脚本版
有一种简单的方法可以在不编写辅助函数的情况下完成此操作......可以在模板中完成 .
编辑:反过来你可以这样做:
编辑/注意:从车把的网站:handlebarsjs.com这里是虚假值:
这是我用于ember 1.10和ember-cli 2.0的方法 .
然后你可以在你的模板中使用它,如下所示:
表达式的参数作为
p0
传递,p1
,p2
等,p0
也可以引用为this
.另一种选择是在
#if
中使用函数名称 .#if
将检测参数是否有效,如果是,那么它将调用它并使用其返回进行真值检查 . myFunction下面的当前上下文为this
.不幸的是,这些解决方案都没有解决“OR”运算符“cond1 || cond2”的问题 .
检查第一个值是否为真
使用“^”(或)并检查cond2是否为真
{}行动{{^}} {}行动{{/ if}} {{/ if}}
它打破了DRY规则 . 那么为什么不使用partial来减少它的混乱
在这里,我们有多个逻辑&&和||的香草把手(和或):
不太确定使用“和”和“或”是否“安全”...可能会更改为“op_and”和“op_or”之类的东西?
类似于吉姆的答案,但使用一点创造力我们也可以这样做:
然后使用它我们得到类似的东西:
我建议将对象移出函数以获得更好的性能,否则你可以添加任何你想要的比较函数,包括“和”和“或” .
这是可以通过块帮手“欺骗”来实现 . 这可能违背了开发Handlebars的人的意识形态 .
然后,您可以像这样在模板中调用帮助程序