Handlebars.js的Else If

291
我正在使用Handlebars.js进行客户端视图渲染。If Else很好用,但我遇到了一个需要ELSE IF的三路条件:

这行不起作用:

{{#if FriendStatus.IsFriend }}
    <div class="ui-state-default ui-corner-all" title=".ui-icon-mail-closed"><span class="ui-icon ui-icon-mail-closed"></span></div>
{{else if FriendStatus.FriendRequested}}
    <div class="ui-state-default ui-corner-all" title=".ui-icon-check"><span class="ui-icon ui-icon-check"></span></div>
{{else}}
    <div class="ui-state-default ui-corner-all" title=".ui-icon-plusthick"><span class="ui-icon ui-icon-plusthick"></span></div>
{{/if}}

如何在 handlebars 中使用 ELSE IF 语句?


请注意Handlebars的更新,看起来很快就会实现:https://github.com/wycats/handlebars.js/pull/892 - Jacob van Lingen
8个回答

452

从3.0.0版本开始,Handlebars支持{{else if}}语句块。

Handlebars v3.0.0或更高版本:

{{#if FriendStatus.IsFriend}}
  <div class="ui-state-default ui-corner-all" title=".ui-icon-mail-closed"><span class="ui-icon ui-icon-mail-closed"></span></div>
{{else if FriendStatus.FriendRequested}}
  <div class="ui-state-default ui-corner-all" title=".ui-icon-check"><span class="ui-icon ui-icon-check"></span></div>
{{else}}
  <div class="ui-state-default ui-corner-all" title=".ui-icon-plusthick"><span class="ui-icon ui-icon-plusthick"></span></div>
{{/if}}

在 Handlebars v3.0.0 之前,您必须定义一个处理分支逻辑的助手函数或手动嵌套 if 语句:

{{#if FriendStatus.IsFriend}}
  <div class="ui-state-default ui-corner-all" title=".ui-icon-mail-closed"><span class="ui-icon ui-icon-mail-closed"></span></div>
{{else}}
  {{#if FriendStatus.FriendRequested}}
    <div class="ui-state-default ui-corner-all" title=".ui-icon-check"><span class="ui-icon ui-icon-check"></span></div>
  {{else}}
    <div class="ui-state-default ui-corner-all" title=".ui-icon-plusthick"><span class="ui-icon ui-icon-plusthick"></span></div>
  {{/if}}
{{/if}}

7
在Handlebars中没有elsif(或else if)的意义在于,你将太多的逻辑放入了模板中。换句话说,你需要将它拆分成更小的模板。 - Kazim Zaidi
2
@KazimZaidi,如果您有一个单独的数据具有三个以上的状态,并且每种状态需要不同的格式,则该怎么办?您可能能够将CSS样式强制放入数据本身中,但这样你就会将视图级别的问题推入到数据中。我可以想象一些明智的情况下使用if/elseif/endif结构(甚至是switch/match)。 - Drew Noakes
1
再看一遍,我觉得这可以通过属性绑定来完成。 - Kazim Zaidi
1
我认为首选的方法是传递布尔标志并对它们进行条件化处理。由您设置标志以使得只有一个条件计算为真。不需要使用 else if - chovy
我建议使用辅助函数来分离您的业务逻辑和演示。 - ChatGPT
如何检查字符串是否为空,如果 var_is_empty,则打印此内容,否则打印那个内容。 - Qadir Hussain

79

我通常使用这个表单:

{{#if FriendStatus.IsFriend}}
  ...
{{else}} {{#if FriendStatus.FriendRequested}}
  ...
{{else}}
  ...
{{/if}}{{/if}}

好的提示,谢谢。这个默认是反应式的吗? - kylemclaren
3
只有一个else if的话看起来很漂亮,但是如果有更多的话,最后一长串的闭合if会变得越来越长 - {{/if}}{{/if}}{{/if}}{{/if}}{{/if}} - jbyrd
2
不,它不是“更简洁”,它更丑陋。 - gene b.

42
Handlebars 现在支持 `{{else if}}` 自 3.0.0 版本起。因此,你的代码现在应该可以正常工作。你可以在 "conditionals" 中看到一个示例(这里稍作修改,并添加了 `{{else}}`)。
    {{#if isActive}}
      <img src="star.gif" alt="Active">
    {{else if isInactive}}
      <img src="cry.gif" alt="Inactive">
    {{else}}
      <img src="default.gif" alt="default">
    {{/if}}

http://handlebarsjs.com/block_helpers.html


无法正常工作(模板中的语法错误)。Meteor 1.2.0.2。 - dragonmnl
@dragonmnl,Meteor 1.2.0.2 使用的 Handlebars 版本是哪个?请确保你正在使用 3.0 版本。 - Don O
我正在使用默认版本。如何检查Handlebars的版本? - dragonmnl
@dragonmnl 看起来Meteor使用自己的模板语言叫做Spacebars。如果是这样的话,我不确定它是否支持{{else if}}语法。 - Don O

38

Handlebars的精神是"无逻辑"的。有时这让我们感觉像是在与它搏斗,有时我们最终会得到丑陋的嵌套if/else逻辑。你可以编写帮助程序;许多人使用“更好”的条件运算符或认为它应该成为核心的一部分来增强handlebars。然而,我认为,与其这样做,

{{#if FriendStatus.IsFriend}}
  <div class="ui-state-default ui-corner-all" title=".ui-icon-mail-closed"><span class="ui-icon ui-icon-mail-closed"></span></div>
{{else}}
  {{#if FriendStatus.FriendRequested}}
    <div class="ui-state-default ui-corner-all" title=".ui-icon-check"><span class="ui-icon ui-icon-check"></span></div>
  {{else}}
    <div class="ui-state-default ui-corner-all" title=".ui-icon-plusthick"><span class="ui-icon ui-icon-plusthick"></span></div>
  {{/if}}
{{/if}}

你可能希望在模型中安排事物,以便你可以拥有这个。

{{#if is_friend }}
  <div class="ui-state-default ui-corner-all" title=".ui-icon-mail-closed"><span class="ui-icon ui-icon-mail-closed"></span></div>
{{/if}}

{{#if is_not_friend_yet }}
    <div class="ui-state-default ui-corner-all" title=".ui-icon-check"><span class="ui-icon ui-icon-check"></span></div>
{{/if}}

{{#if will_never_be_my_friend }}
    <div class="ui-state-default ui-corner-all" title=".ui-icon-plusthick"><span class="ui-icon ui-icon-plusthick"></span></div>
{{/if}}

请确保这些标志中只有一个为真。如果您在视图中使用此 if/elsif/else ,那么很有可能您也在其他地方使用它,因此这些变量可能不会是多余的。

保持简洁。


1
我不确定这是否是一种好的做法,但今天在处理3个不同的视图状态时,我使用了基于此解决方案(他们的elseif逻辑并不重要,因为它们都针对一个值进行检查)。http://stackoverflow.com/questions/15008564/meteor-template-not-updating-using-click-event 因此,您可以使用一个非常简单的助手字符串代替#if_is_friend(在其答案中):#if friend_type“is_friend”,#if friend_type“is_not_friend_yet”。 - Dylan Reich
这个答案是我认为在handlebars 3.0之前最好的解决方案,我认为额外的HTML比试图将逻辑塞入DOM树更好。 - David O'Regan

7
我写了这个简单的助手:
Handlebars.registerHelper('conditions', function (options) {
    var data = this;
    data.__check_conditions = true;
    return options.fn(this);
});


Handlebars.registerHelper('next', function(conditional, options) {
  if(conditional && this.__check_conditions) {
      this.__check_conditions = false;
      return options.fn(this);
  } else {
      return options.inverse(this);
  }
});

这类似于Handlebars中的责任链模式。

例如:

    {{#conditions}}
        {{#next condition1}}
            Hello 1!!!
        {{/next}}
        {{#next condition2}}
            Hello 2!!!
        {{/next}}
        {{#next condition3}}
            Hello 3!!!
        {{/next}}
        {{#next condition4}}
            Hello 4!!!
        {{/next}}
    {{/conditions}}

虽然它不是一个else if,但在某些情况下它可能对你有帮助。


3
内置助手
#if

你可以使用if助手来有条件地渲染一个块。如果它的参数返回false、undefined、null、""、0或[],Handlebars将不会渲染该块。
模板
<div class="entry">
  {{#if author}}
    <h1>{{firstName}} {{lastName}}</h1>
  {{else}}
    <h1>Unknown Author</h1>
  {{/if}}
</div>

当您将以下输入传递给上述模板时:
{
  author: true,
  firstName: "Yehuda",
  lastName: "Katz"
}

1

在handlebars中首先注册一个如下的函数

Handlebars.registerHelper('ifEquals', function(arg1, arg2, options) {
    return (arg1 == arg2) ? options.fn(this) : options.inverse(this);
});

您可以注册多个函数。要添加另一个函数,只需像下面这样添加

Handlebars.registerHelper('calculate', function(operand1, operator, operand2) {
    let result;
    switch (operator) {
        case '+':
            result = operand1 + operand2;            
            break;
        case '-':
            result = operand1 - operand2;            
            break;
        case '*':
            result = operand1 * operand2;            
            break;
        case '/':
            result = operand1 / operand2;            
            break;
    }

    return Number(result);
});

在 HTML 页面中只需包含条件即可,例如:

    {{#ifEquals day "mon"}}
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
      //html code goes here
    </html>
   {{else ifEquals day "sun"}}
    <html>
     //html code goes here
    </html>
   {{else}}
     //html code goes here
   {{/ifEquals}}

0

你好,我只需要进行一个小的类名编辑,目前我已经这样做了。我认为我需要向辅助程序传递多个参数。

server.js

app.engine('handlebars', ViewEngine({
        "helpers":{
                isActive: (val, options)=>{
                    if (val === 3 || val === 0){
                        return options.fn(this)
                    }
                } 
        }
}));

header.handlebars

<ul class="navlist">
          <li   class="navitem navlink {{#isActive 0}}active{{/isActive}}"
                ><a href="#">Home</a></li>
          <li   class="navitem navlink {{#isActive 1}}active{{/isActive}}"
                ><a href="#">Trending</a></li>
          <li   class="navitem navlink {{#isActive 2}}active{{/isActive}}"
                ><a href="#">People</a></li>
          <li   class="navitem navlink {{#isActive 3}}active{{/isActive}}"
                ><a href="#">Mystery</a></li>
          <li class="navitem navbar-search">
            <input type="text" id="navbar-search-input" placeholder="Search...">
            <button type="button" id="navbar-search-button"><i class="fas fa-search"></i></button>
          </li>
        </ul>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接