【问题标题】:complex template composition in MustacheMustache 中的复杂模板组合
【发布时间】:2013-02-11 20:51:13
【问题描述】:

考虑一个显示用户冰箱内容的 Web 应用程序。除其他外,需要显示当前在冰箱中的水果列表。每种水果都需要非常不同的展示方式。最重要的是,会有大量不同的水果类型。

我想使用 Mustache 模板库来实现这一点,但我不太确定最好的方法是什么。

首先,以下是每种水果的模板:

{{! apple.mustache }}
A {{appleType}} apple from {{groceryStore}}

{{! orange.mustache }}
An orange from {{countryOfOrigin}}

{{! banana.mustache }}
A {{ripeness}} banana

...many more templates here...

方法 1

让“视图模型”或“视图助手”对象通过创建“isBanana”/“isOrange”/等来准备模板数据。将传递给模板的键。在这种情况下,冰箱模板看起来像这样:

You have the following food in your fridge:

{{#fruits}}
        {{#isApple}}
                {{> apple}}
        {{/isApple}}
        {{#isOrange}}
                {{> orange}}
        {{/isOrange}}
        {{#isBanana}}
                {{> banana}}
        {{/isBanana}}
        ...more conditionals....
{{/fruits}}

我已经看到这种方法在互联网上推荐了几个地方。但是,我看不出它会如何扩展:每次添加新的水果类型时都必须修改冰箱模板。这似乎也违背了 Mustache 的“无逻辑”哲学。

方法 2

让视图模型负责为每种水果类型确定正确的模板,渲染它,并将 HTML 作为模板数据返回。冰箱模板现在看起来像:

You have the following food in your fridge:

{{{fruits}}}

还有视图模型:

class InventoryViewModel
{
    // ...

    function getFruits()
    {
        foreach ($this->fridge->getFruits() as $fruit) {
            if ($fruit instanceof Banana) {
                $html .= $this->mustache->render(...);
            } elseif ($fruit instanceof Apple) {
                $html .= $this->mustache->render(...);
            } else {
                // ...
            }
        }

        return $html;
    }
}

这似乎比第一个选项更好,但它需要将一个 mustache 模板渲染对象注入到每个视图模型中。如果可能的话,我想避免这种耦合。

方法 3

使用某种不属于 Mustache 官方规范的模板组合功能。 (https://github.com/janl/mustache.js/pull/242https://github.com/mustache/spec/issues/38 等)。

哪些选项最好,为什么?我是否忽略了更好的东西?

【问题讨论】:

    标签: templates template-engine mustache


    【解决方案1】:

    可能最简单的方法是在 ViewModel 中使用高阶部分(lambda 部分)来为您选择部分。

    您的基本模板如下所示:

    {{# items }}
      {{# getPartial }}{{ type }}{{/ getPartial }}
    {{/ items }}
    

    当然,假设您的水果有“类型”。然后为getPartial 添加一个高阶部分:

    <?php
    
    class InventoryViewModel
    {
        // ...
    
        function getPartial()
        {
            // you could do string manipulation here,
            // but I prefer the explicitness of a `case`
    
            return function($tpl, $mustache) {
                switch ($mustache->render($tpl)) {
                    case 'Banana':
                        return '{{> banana }}';
                    case 'Apple':
                        return '{{> apple }}';
                    case 'Orange':
                        return '{{> orange }}';
                }
            };
        }
    }
    

    在这种情况下,您的模板通过将逻辑移动到其随附的 ViewModel 来保持“无逻辑”,可以在其中进行单元测试、模拟等。

    【讨论】:

      猜你喜欢
      • 2011-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-09
      • 1970-01-01
      相关资源
      最近更新 更多