如何处理 Meteor 模板中的 switch case

Posted

技术标签:

【中文标题】如何处理 Meteor 模板中的 switch case【英文标题】:How to handle switch cases in Meteor templates 【发布时间】:2013-07-12 17:17:46 【问题描述】:

在模板中处理 switch case 的最佳方法是什么(例如:具有 4 种可能状态的按钮)?把 html 拉出来放到 helper 里好像是不对的,但是把逻辑放到模板里感觉一样糟糕……

编辑:

如您所见,将 html 放在帮助程序中远非理想,但更改类、标记名、属性和内容会使模板完全不可读。

Template.nextMeetup.helpers(
    rsvpButton: function(rsvp) 
        var button;

        switch(rsvp)
            case 'yes':
                button = '<a ' + this.event_url + 'class="rsvp btn btn-success pull-right" title="visit event page" target="_blank"><i class="icon-check"></i> I\'m Attending</a>';
            break;
            case 'maybe':
                button = '<a ' + this.event_url + 'class="rsvp btn btn-warning pull-right" title="visit event page" target="_blank"><i class="icon-warning-sign"></i> I might go</a>';
            break;
            case 'no':
                button = '<a ' + this.event_url + 'class="rsvp btn btn-danger pull-right" title="visit event page" target="_blank"><i class="icon-remove"></i> I\'m not going</a>';
            break;
            case 'none':
                button = '<a ' + this.event_url + 'class="rsvp btn btn-inverse pull-right" title="visit event page" target="_blank"><i class="icon-spinner"></i> I havn\'t decided</a>';
            break;
            default:
                button = '<button class="rsvp signIn btn btn-disabled pull-right">Sign in to RSVP</button>';
        
        return new Handlebars.SafeString(button);
    
);

【问题讨论】:

【参考方案1】:

不确定您要输出什么,但可能会涉及评估相等性的助手。将其放入您项目的一个客户端加载的 javascript 文件中:

Template.registerHelper("equals", function (a, b) 
  return (a == b);
);

然后您可以使用if 块和新的equals 助手创建类似于switch-case 结构的东西。例如,如果您将按钮的状态存储在名为btnState 的变量中,并且可能的值为123

<button class="#if equals btnState 1btn-active/if
               #if equals btnState 2btn-inactive/if
               #if equals btnState 3btn-disabled
               elsebtn-default/if">

如果您希望switch-case 在达到真值和/或最后的默认情况后短路进一步测试的能力,那么这样做的方法是使用一组丑陋的嵌套if-else 块:

<button class="#if equals btnState 1
                 btn-active
               else
                 #if equals btnState 2
                   btn-inactive
                 else
                   #if equals btnState 3
                     btn-disabled
                   else
                     btn-default
                   /if
                 /if
               /if">

这个例子非常简单;我假设您将它用作大型模板的控制结构,而不是像 btn-default 这样的东西,您有几十行 HTML。

如果您真的将它用于短的 sn-ps 文本(如 CSS 类名),则可以改为创建一个帮助器,将一组案例映射到一组要返回的字符串。例如(CoffeeScript):

Template.registerHelper "switch", (input, cases, output, def) ->
  # input is the variable we're comparing, i.e. switch(input)
  # cases is an EJSON-stringified array, i.e. case "foo", case "bar"
  # output is an EJSON-stringified array of strings to return for each case
  # def (default) is a string to return if none of the cases are met

  # Validate input, convert EJSON strings into arrays:
  unless input? and _.isString(cases) and _.isString(output)
    return ""
  cases = EJSON.parse cases
  output = EJSON.parse output
  unless _.isArray(cases) and _.isArray(output) and 
    cases.length is output.length
      return ""

  # Evaluate each case, returning as soon as the first case is true:
  for value, index in cases
    return output[index] if input is value

  # If we've made it this far, none of the cases were met; return def (default):
  if def? and _.isString(def) then return def else return ""

并使用它:

switch btnState "[1,2,3]"
  "[\"btn-active\",\"btn-inactive\",\"btn-disabled\"]" "btn-default"

Handlebars 不允许将数组或对象传递给帮助程序,因此 JSON 字符串作为参数传递然后被解析会产生扭曲。

【讨论】:

感谢您的深入回复,但正如我担心的那样,答案似乎是:没有好的方法 :( 模板中间的 if/else/switch 看起来已经很乱了,而且只有一个属性更改(我打算更改类、属性和内容)。“切换助手”看起来更合理,但似乎很脆弱和​​做作。我想我希望有一种常见的做法来处理类似的事情这个。 您仍然可以将内容与逻辑分开。您可以为每个按钮制作一组子模板(部分)。然后,如果您想使用您的助手,请将 HTML 字符串替换为 Template.btnYes(rsvp: rsvp)Meteor.render(function() Template.btnYes(rsvp: rsvp) )。或者制作一个名为 button 的部分,它使用丑陋的 if-else 块,并为每个按钮包含子部分。通过&gt; button 包含它 我从没想过要从助手内部引用模板,谢谢,我认为这样会很好用。 我认为对于一般情况,equals 助手是最好的选择。它本质上只是在渲染模板之前为每个可能值创建布尔变量的快捷方式,例如isBtnState1isBtnState2 等,这是 Handlebars 推荐的简单案例处理方式。 为了让这对我有用,我必须在 equals 语句周围添加括号,如下所示:#if (equals btnState 1)btn-active/if。这些是必需的,因为equals 是一个子表达式 (handlebarsjs.com/expressions.html#subexpressions)【参考方案2】:

每个按钮使用一个模板和一个额外的动态模板

你的模板助手,返回动态模板:

Template.nextMeetup.helpers(
    rsvpButtonTemplate: function(rsvp) 
        switch(rsvp)
            case 'yes':   return Template.buttonYes;
            case 'maybe': return Template.buttonMaybe;
            case 'no':    return Template.buttonNo;
            case 'none':  return Template.buttonNone;
        
    
);

你的主模板,调用模板助手:

<template name="myPage">
    ...
    > rsvpButtonTemplate
    ...
</template>

您的 4 个按钮:

<template name="buttonYes">
    <a event_url class="rsvp btn btn-success pull-right" title="visit event page" target="_blank"><i class="icon-check"></i> I'm Attending</a>
</template>
<template name="buttonMaybe">
    <a event_url class="rsvp btn btn-warning pull-right" title="visit event page" target="_blank"><i class="icon-warning-sign"></i> I might go</a>
</template>
<template name="buttonNo">
    <a event_url class="rsvp btn btn-danger pull-right" title="visit event page" target="_blank"><i class="icon-remove"></i> I'm not going</a>
</template>
<template name="buttonNone">
    <a event_url class="rsvp btn btn-inverse pull-right" title="visit event page" target="_blank"><i class="icon-spinner"></i> I havn't decided</a>
</template>

【讨论】:

以上是关于如何处理 Meteor 模板中的 switch case的主要内容,如果未能解决你的问题,请参考以下文章

如何处理 C++ 内联 + 模板上下文中的警告?

Selenium 如何处理多层嵌套 iframe

如何处理 NSPersistentContainer.loadPersistentStores 中的错误?

如何处理 Codeigniter 模板?

如何处理ios目标c中的解析通知?

在flask中提交数据时如何处理错误