代码之家  ›  专栏  ›  技术社区  ›  Morgan Cheng

无逻辑模板(如胡子)的优点是什么?

  •  95
  • Morgan Cheng  · 技术社区  · 14 年前

    mustache 据称是 无逻辑模板

    然而,并不能解释为什么它是以逻辑较少的方式设计的。换句话说,无逻辑模板的优点是什么?

    13 回复  |  直到 14 年前
        1
  •  106
  •   Miguel Ping    14 年前

    换句话说,它可以防止你射中自己的脚。在旧的JSP时代,JSP文件中散布Java代码是非常常见的,这使得重构变得更加困难,因为您的代码是分散的。

    按设计

    另一个优点是,您被迫从关注点的分离角度进行思考:您的控制器或逻辑代码将必须处理数据 按摩

        2
  •  66
  •   Emile Bergeron Dhaval Rajpara    7 年前

    我觉得在我看来我几乎是孤独的,但我坚定地站在相反的阵营里。我不认为在模板中可能混合业务逻辑是不使用编程语言全部功能的充分理由。

    无逻辑模板的常见论点是,如果您可以完全访问编程语言,那么您可能会在模板中没有位置的逻辑中进行混合。我发现这类似于你应该用勺子切肉的推理,因为如果你用刀的话,你可以把自己切了。这是非常正确的,但是如果你使用后者,你会更有效率,尽管要小心。

    mustache :

    {{name}}:
    <ul>
      {{#items}}
        <li>{{.}}</li>
      {{/items}}
    </ul>
    

    我能理解,但我发现 underscore

    <%- name %>:
    <ul>
    <% _.each(items, function(i){ %>
      <li><%- i %></li>
    <% }); %>
    </ul>
    

        3
  •  28
  •   pje    12 年前

    胡子少逻辑吗?

    这不是:

    {{#x}}
      foo
    {{/x}}
    {{^x}}
      bar
    {{/x}}
    

    和这个很相似?

    if x
      "foo"
    else
      "bar"
    end
    

    而不是 非常类似于(读:几乎是一个定义)表示逻辑?

        4
  •  13
  •   Jeremy    14 年前

    mustache manual :

    不是if语句、else子句或 对于循环。相反,只有 标签。一些标记被替换为 价值,有些什么都没有,还有一些 一系列的价值观。本文件 解释不同类型的

        5
  •  12
  •   mattmc3    12 年前

    问题的另一面是,为了将业务逻辑排除在演示之外,您最终会在模型中放置大量的演示逻辑。一个常见的例子可能是,您希望将“奇数”和“偶数”类放在表中的交替行上,这可以使用视图模板中的简单模运算符来完成。但是,如果视图模板不允许这样做,那么在模型数据中,不仅要存储奇数或偶数行,还要根据模板引擎的限制程度,甚至可能需要用实际CSS类的名称污染模型。视图应与模型分离,完全停止。但是模型也应该是视图不可知的,这就是许多“无逻辑”模板引擎让您忘记的。逻辑在两个地方都有,但是你必须对逻辑 实际上是的 正确决定它的去向。是表示问题,还是业务/数据问题?为了获得100%的原始景观,污染只是降落在另一个不太明显但同样不合适的地方。

    There's a growing movement back in the other direction, 希望事情能以更合理的中间立场为中心。

        6
  •  11
  •   blockhead    14 年前

        7
  •  8
  •   David Balme    12 年前

    小咆哮接踵而至(请随意忽略):

    如果你不想继续阅读。。我对上述问题的简短答复是:

    现在我的咆哮继续如火如荼地进行着:

    我认为当你把许多想法发挥到极致时,结果就变得可笑了。有时(这个话题)问题是我们把“错误”的想法发挥到了极致。

    往后退一步。

    我们需要问自己的问题是,为什么要去掉逻辑?这个概念,显然是 separation of concerns . 使视图处理尽可能与业务逻辑分开。为什么这么做?它允许我们交换视图(对于不同的平台:移动、浏览器、桌面等),并且它允许我们更容易地交换控制流、页面序列、验证更改、模型更改、安全访问等,同时当逻辑从视图(尤其是web视图)中移除时,它使视图更具可读性,因此更易于维护。我明白并且同意。

    然而,最重要的重点应该是关注点的分离。不是100%逻辑的观点。视图中的逻辑应该与如何呈现“模型”相关。就我而言,观点中的逻辑是完全正确的。您可以使用不是业务逻辑的视图逻辑。

    因此,来自高层(行业专家)的命令变成,你必须使用类似于前视图控制器(发送给处理程序或操作[选择你的web框架])的东西来构建你的web应用,你的视图必须不包含代码。视图将变成哑模板。

    在我参与的一个项目中,我们试图遵循逻辑较少的观点,达到可笑的极端。我们有一个自己开发的模板引擎,它允许我们在html中呈现模型对象。这是一个简单的基于令牌的系统。这很可怕,原因很简单。有时在我们不得不决定的一个视图中,我是否应该显示这个HTML的小片段。。或者不。。决策通常基于模型中的某些值。当你完全没有逻辑的观点,你怎么做?你不能。关于这件事,我和我们的建筑师有一些主要的争论。编写我们的视图的前端HTML人员在面对这一点时完全束手无策,压力很大,因为他们无法实现原本简单的目标。所以我在我们的模板引擎中引入了一个简单IF语句的概念。我无法向你描述随之而来的解脱和平静。在我们的模板中用一个简单的IF语句概念解决了这个问题!突然我们的模板引擎变好了。

    那么,我们是怎么陷入这种无聊的压力境地的呢?我们把注意力集中在错误的目标上。我们遵循规则,你的观点不能有任何逻辑。那是错误的。我认为“经验法则”应该是,尽量减少你观点中的逻辑。因为如果不这样做,您可能会无意中允许业务逻辑潜入视图,这违反了关注点的分离。

    当我在视图中看到很多逻辑时,我会检测到一种代码味道,并尝试从视图中消除大部分逻辑——我试图确保业务逻辑存在于其他地方——我试图分离关注点。但是当我开始和那些说我们 必须 对我来说,把所有的逻辑都去掉,好吧,对我来说,那只是狂热的一点,因为我知道你可能会在我上面描述的情况下结束。

    干杯,

    大卫

        8
  •  5
  •   eagspoo    13 年前

    另一个选择是找到一个模板语法,它使用客户机和服务器都支持的语言,即服务器上的javascript,可以使用node.js,也可以通过rubyracer之类的工具使用js解释器和js on。

        9
  •  4
  •   Kernel James    13 年前

    在一句话中:逻辑更少意味着模板引擎本身不那么复杂,因此占用空间更小,并且有更少的方式让它意外地运行。

        10
  •  3
  •   Lucero    13 年前

    尽管这个问题已经过时并得到了回答,我还是想加上我的2(这听起来像是在咆哮,但事实并非如此,这是关于限制和当它们变得不可接受时)。

    模板的目标是呈现某些内容,而不是执行业务逻辑。现在,在不能在模板中执行需要执行的操作和在模板中包含“业务逻辑”之间有了一条细线。尽管我对胡子很有信心,并尝试使用它,但我最终无法在非常简单的情况下做我需要的事情。

    数据的“按摩”(使用公认答案中的单词)可能成为一个真正的问题——甚至不支持简单的路径(Handlebars.js提供的地址)。如果我有视图数据,我需要调整,每次我想渲染的东西,因为我的模板引擎太有限,那么这在最后是没有帮助的。而且它也破坏了mustache声称的平台独立性的一部分;我必须在任何地方复制按摩逻辑。

    @name:
    <ul>
    @for (items) {
      <li>@.</li>
    }
    </ul>
    

    另一个没有逻辑限制的问题是,当我们调用带有胡子的partials时。虽然partials是由Mustache支持的,但是不可能首先自定义要传入的数据。因此,与其创建模块化模板并重用小的块,我将在模板中使用重复的代码。

    假设我们希望呈现一个“数据网格”表,其中包含可定制的标题和指向行上操作的链接,然后使用jQuery动态添加行。因此,如果我不想复制代码,行必须是部分的。如果某些附加信息(如应呈现哪些列)是viewmodel的一部分,并且每行上的这些操作都是相同的,那么问题就由此开始了。下面是一些使用我们的模板和查询引擎的实际工作代码:

    <table>
        <thead>
            <tr>
                @for (columns) {
                    <th>@title</th>
                }
                @if (actions) {
                    <th>Actions</th>
                }
            </tr>
        </thead>
        <tbody>
            @for (rows) {
                @partial Row({ row: ., actions: $.actions, columns: $.columns })
            }
        </tbody>
    </table>
    

    行模板:

    <tr id="@(row.id)">
        @for (var $col in columns) {
            <td>@row.*[name()=$col.property]</td>
        }
        @if (actions) {     
            <td>
            @for (actions) {
                <button class="btn @(id)" value="@(id)">@(name)...</button>
            }
            </td>
        }
    </tr>
    

    从JS代码调用:

    var html = table({
        columns: [
            { title: "Username", property: "username" },
            { title: "E-Mail", property: "email" }
        ],
        actions: [
            { id: "delete", name: "Delete" }
        ],
        rows: GetAjaxRows()
    })
    

    它没有任何业务逻辑,但它是可重用和可配置的,而且它也没有副作用。

        11
  •  2
  •   Dean Radcliffe    11 年前

    咖啡脚本(带 Reactive Coffee

    "#{name}"
    ul items.map (i) ->
      li i
    

    击倒-100个字符

    <span data-bind="value: name"/>
    <ul data-bind="foreach: items">
       <li data-bind="value: i"/>
    </ul>
    

    车把/胡子-66个字符

    {{name}}:
    <ul>
      {{#items}}
        <li>{{.}}</li>
      {{/items}}
    </ul>
    

    下划线-87个字符

    <%- name %>:
    <ul>
    <% _.each(items, function(i){ %>
      <li><%- i %></li>
    <% }); %>
    </ul>
    

    我认为,无逻辑模板的承诺是,拥有更广泛技能集的人将能够管理无逻辑模板,而不会自相残杀。然而,您在上面的示例中看到的是,当您向基于字符串的标记添加最小逻辑语言时,结果会更复杂,而不是更少。而且,你看起来像在做老式的PHP。

    显然,我并不反对将“业务逻辑”(广泛的计算)排除在模板之外。但我认为,通过给它们一种伪语言而不是一级语言来显示逻辑,代价是付出的。不仅仅是打字,还有一个令人发指的上下文转换需要有人阅读。

    最后,我看不到无逻辑模板的逻辑,所以我认为它们的优势对我来说是零,但我尊重社区中许多人的不同看法:)

        12
  •  2
  •   rmuller    7 年前

    • 严格地 ,请参见 this paper
    • 非常 易于理解和使用 ,因为没有编程逻辑(和知识!)是必需的,并且语法是最小的
    • (特别是胡子)高度 便携式的
        13
  •  1
  •   roland    11 年前

    我同意布拉德的观点 underscore _.each 有点混乱,你可以用传统的 for 循环。

      <% for(var i = 0; i < items.length; i++) { %>
        <%= items[i] %>
      <% } %>
    

    对于 if . 只是使用 <% if() %> <% for() %> Mustache 用一些新词 if-then-else (如果您没有阅读文档,您会感到困惑):

    {{#x}}
      foo
    {{/x}}
    {{^x}}
      bar
    {{/x}}
    

    当您可以轻松地实现嵌套模板时,模板引擎非常好( 强调 风格):

    <script id="items-tmpl" type="text/template">
        <ul>
            <% for(var i = 0; i < obj.items.length; i++) { %>
                <%= innerTmpl(obj.items[i]) %>
            <% } %>
        </ul>
    </script>
    
    <script id="item-tmpl" type="text/template">
        <li>
            <%= name %>
        </li>
    </script>
    
    var tmplFn = function(outerTmpl, innerTmpl) {
        return function(obj) {
            return outerTmpl({obj: obj, innerTmpl: innerTmpl});
        };
    };
    
    var tmpl = tmplFn($('#items-tmpl').html(), $('#item-tmpl').html());
    var context = { items: [{name:'A',{name:'B'}}] };
    tmpl(context);
    

    只有900个字符

    https://gist.github.com/marlun78/2701678