如何在mustache.js中实现if/else语句?

306

我觉得很奇怪,我无法弄清楚在Mustache模板中如何实现这个。这个功能被支持吗?

以下是我失败的尝试:

    {{#author}}
      {{#avatar}}
        <img src="{{avatar}}"/>
      {{/avatar}}
      {{#!avatar}}
        <img src="/images/default_avatar.png" height="75" width="75" />
      {{/avatar}}
    {{/author}}

显然这不是正确的,但文档中没有提到任何类似的内容。甚至没有提到“else”这个词 :(

此外,为什么mustache要设计成这样?这种情况是否被认为是不好的?它是试图强制我在模型本身中设置默认值吗?那些不可能的情况呢?


1
“为什么Mustache被设计成这样?”我不太确定,但我认为这个想法是模板语言应该只是一个用于编写模板的语言,也就是看起来像它们产生的输出,只是有变量部分的空洞。在模板语言中加入逻辑会使模板更加复杂,而当你已经有一种编程语言来处理逻辑时,为什么还要麻烦呢? - Paul D. Waite
6
“无逻辑(Logic-less)”实际上是指“非武断的代码(non-arbitrary code)”,我认为。在代码中放置真正意义上的逻辑和将非视图逻辑放置在模板中一样糟糕。Mustache试图提供最基本的逻辑来实现这一点。 - jpmc26
2
或者使用handlebars代替mustache。能够编写例如{{#each items}}{{#unless @first}}在第2、3、4个之前输出逗号{{/unless}}{{/each}}更易读,更清晰,仍然是表现层。"无逻辑"只是一个指导方针,它不必成为一种约束。 - skierpage
也许当一个 OP 说“这是我可悲的尝试[...]这显然不对”的时候,这个模板引擎并不够灵活。然后被接受的答案是那段代码的复制粘贴 : ) 。对 OP 或答案没有任何评判;只是对 mustache 表达了一些看法。 - dwanderson
如果你在使用PHP,可以尝试使用sm-mustache,我已经实现了|的else块来减少那些额外的声明。 - Michael Quad
5个回答

580

以下是在Mustache中使用if/else的方法(完美支持):

{{#repo}}
  <b>{{name}}</b>
{{/repo}}
{{^repo}}
  No repos :(
{{/repo}}

或者在你的情况下:

{{#author}}
  {{#avatar}}
    <img src="{{avatar}}"/>
  {{/avatar}}
  {{^avatar}}
    <img src="/images/default_avatar.png" height="75" width="75" />
  {{/avatar}}
{{/author}}

在文档中寻找反转的部分:https://github.com/janl/mustache.js#inverted-sections


134
胡子文件非常有趣。"我们称之为“无逻辑”因为没有if语句、else语句或for循环。" - boxed
8
@boxed,从技术上讲,你是正确的,反转部分是一个逻辑语句,因为它检查标签值。但我认为这里的细微差别在于,必须明确评估两个语句,而不是单一的if/else语句。基本上,mustache强制结构为if(condition){ //执行某些操作},然后是if(!condition){//执行其他操作}。此外,在逻辑方面,可以执行的逻辑数量极其有限,与基于逻辑的语言相比大为降低。存在或不存在是唯一的检查方式,也就是说,不能检查标签的值是否等于5,然后进入该标签的代码中。 - MandM
29
@MandM 是的…所以它是有逻辑的,但它无法做任何有用的事情 :P - boxed
1
它可以让你远离 if else 逻辑的混乱。在一个 if/else 嵌套另一个 if/else 的情况下,这是设计不良的标志。 - Tebe
@boxed,你可以使用Moustache.js来进行for循环(至少类似于ngFor的循环)。 - aloisdg
显示剩余2条评论

59
这是在“控制器”中解决的问题,它是无逻辑模板的关键点。
// some function that retreived data through ajax
function( view ){

   if ( !view.avatar ) {
      // DEFAULTS can be a global settings object you define elsewhere
      // so that you don't have to maintain these values all over the place
      // in your code.
      view.avatar = DEFAULTS.AVATAR;
   }

   // do template stuff here

}

这实际上比维护图像URL或其他可能在模板中更改或不更改的媒体要好得多,但需要一些时间来适应。关键是要放弃模板隧道视野,头像图片URL必定会在其他模板中使用,你会在X个模板中维护该URL还是单个DEFAULTS设置对象中?;)

另一个选项是执行以下操作:

// augment view
view.hasAvatar = !!view.avatar;
view.noAvatar = !view.avatar;

在模板中:

{{#hasAvatar}}
    SHOW AVATAR
{{/hasAvatar}}
{{#noAvatar}}
    SHOW DEFAULT
{{/noAvatar}}

但这与无逻辑模板的整体意义相违背。如果这是你想要做的事情,你需要使用逻辑模板而不是Mustache,尽管你应该给自己一个公平的机会学习这个概念 ;)


谢谢。太好了,这实际上还帮助我解决了其他有关javascript代码结构中“何时执行操作”的结构方面的问题。 - egervari
{{/#hasAvatar}} 和 {{/#noAvatar}} 在这个答案中应该改为 {{/hasAvatar}} 和 {{/noAvatar}}。 - Mulhoon

17

你的else语句应该像这样(注意^):

{{^avatar}}
 ...
{{/avatar}}

在 Mustache 中,这被称为“反转节”(Inverted sections)。


7
请注意,您不需要同时使用 # 和 ^ 符号,仅在 "not" 的情况下使用 ^ 符号即可。 - zappan
最新版本中无法运行。Zappan是正确的,你只需要^。 - simonmorley

15

请注意,您可以使用{{.}}来呈现当前上下文项。

{{#avatar}}{{.}}{{/avatar}}

{{^avatar}}missing{{/avatar}}

0

您可以在视图中定义一个帮助程序。但是,条件逻辑有些受限。Moxy-Stencil(https://github.com/dcmox/moxyscript-stencil)似乎通过“参数化”帮助程序来解决这个问题,例如:

{{isActive param}}

在视图中:

view.isActive = function (path: string){ return path === this.path ? "class='active'" : '' }


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