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

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

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


当前回答

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

{{#if myFunction}}
  I'm Happy!
{{/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" numbertwo}}
  do something
{{else}}
  do something else
{{/compare}}

我建议将对象移出函数以获得更好的性能,否则您可以添加任何您想要的比较函数,包括“and”和“or”。

为了那些生活在边缘的人,把这个提升一个档次。

要点:https://gist.github.com/akhoury/9118682 演示:下面是代码片段

句柄Helper: {{#xif表达式}}{{else}} {{/xif}}

一个helper来执行带有任意表达式的IF语句

EXPRESSION是一个正确转义的字符串 是的,你需要正确转义字符串字面量或只是交替单引号和双引号 您可以访问任何全局函数或属性,即encodeURIComponent(property) 这个例子假设你将这个上下文传递给你的handlebars模板({name: 'Sam', age: '20'}),注意年龄是一个字符串,只是为了我可以在后面的文章中演示parseInt()

用法:

<p>
 {{#xif " name == 'Sam' && age === '12' " }}
   BOOM
 {{else}}
   BAMM
 {{/xif}}
</p>

输出

<p>
  BOOM
</p>

JavaScript:(这取决于另一个助手-继续阅读)

 Handlebars.registerHelper("xif", function (expression, options) {
    return Handlebars.helpers["x"].apply(this, [expression, options]) ? options.fn(this) : options.inverse(this);
  });

帮助句柄:{{x表达式}}

一个执行javascript表达式的助手

EXPRESSION是一个正确转义的字符串 是的,你需要正确转义字符串字面量或只是交替单引号和双引号 你可以访问任何全局函数或属性,即parseInt(property) 这个例子假设你将这个上下文传递给了你的handlebars模板({name: 'Sam', age: '20'}),年龄是一个用于演示的字符串,它可以是任何东西。

用法:

<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)); h1 { font-size: large; } .content { padding: 10px; } .person { padding: 5px; margin: 5px; border: 1px solid grey; } <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>

Moar

如果你想访问上层作用域,这个略有不同,表达式是所有参数的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}}

Javascript:

Handlebars.registerHelper("z", function () {
    var options = arguments[arguments.length - 1]
    delete arguments[arguments.length - 1];
    return Handlebars.helpers["x"].apply(this, [Array.prototype.slice.call(arguments, 0).join(''), options]);
});

Handlebars.registerHelper("zif", function () {
    var options = arguments[arguments.length - 1]
    delete arguments[arguments.length - 1];
    return Handlebars.helpers["x"].apply(this, [Array.prototype.slice.call(arguments, 0).join(''), options]) ? options.fn(this) : options.inverse(this);
});

有一种简单的方法可以做到这一点,而不需要编写helper函数…它完全可以在模板中完成。

{{#if cond1}}   
  {{#if con2}}   
    <div> and condition completed</div>  
  {{/if}}
{{else}}   
  <div> both conditions weren't true</div>  
{{/if}}

编辑:相反,你可以这样做或's:

{{#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}}

编辑/注:来自车把网站:handlebarsjs.com的错误值如下:

你可以使用if helper来有条件地呈现一个块。如果它的 参数返回false, undefined, null, ""或[](一个" false "值), 那么任何“cond”(如cond1或cond2)都不会被视为真。

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

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”之类的?

这里发布的所有答案的一个问题是,它们不能与绑定属性一起工作,即当涉及的属性发生变化时,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}}