考虑一个显示用户冰箱内容的 Web 应用程序。除其他外,需要显示当前在冰箱中的水果列表。每种水果都需要非常不同的展示方式。最重要的是,会有大量不同的水果类型。
我想使用 Mustache 模板库来实现它,但我不太确定最好的方法是什么。
对于初学者,以下是每种水果的模板:
{{! apple.mustache }}
A {{appleType}} apple from {{groceryStore}}
{{! orange.mustache }}
An orange from {{countryOfOrigin}}
{{! banana.mustache }}
A {{ripeness}} banana
...many more templates here...
方法一
让“视图模型”或“视图助手”对象通过创建“isBanana”/“isOrange”/等来准备模板数据。将传递给模板的键。在这种情况下,冰箱模板看起来像这样:
You have the following food in your fridge:
{{#fruits}}
{{#isApple}}
{{> apple}}
{{/isApple}}
{{#isOrange}}
{{> orange}}
{{/isOrange}}
{{#isBanana}}
{{> banana}}
{{/isBanana}}
...more conditionals....
{{/fruits}}
我已经看到这种方法在互联网上推荐了几个地方。但是,我看不出它会如何扩展:每次添加新的水果类型时都必须修改冰箱模板。这似乎也违背了 Mustache 的“无逻辑”哲学。
方法二
让视图模型负责为每种水果类型确定正确的模板,渲染它,并将 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/242、https://github.com/mustache/spec/issues/38等)。
这些选项中哪个是最好的,为什么?我是否忽略了更好的东西?