2013-02-11 89 views
0

考慮一個顯示用戶冰箱內容的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}} 

我見過這種方法推薦了幾個地方在互聯網上。但是,我看不到它會如何縮放:每次添加新的水果類型時,必須修改冰箱模板。它似乎也在反對胡斯塔的「無邏輯」哲學。

方法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; 
    } 
} 

的似乎比第一種辦法比較好,但它需要注入鬍子模板渲染對象到每個視圖模型。如果可能,我想避免這種耦合。

方法3

使用某種模板組成特徵,這不是官方的鬍子規範的一部分。 (https://github.com/janl/mustache.js/pull/242https://github.com/mustache/spec/issues/38等)。

以下哪個選項最好?爲什麼?我能看到更好的東西嗎?

回答

3

也許最簡單的是在您的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 }}'; 
      } 
     }; 
    } 
} 

在這種情況下,您的模板通過移動邏輯與之配套的視圖模型,在那裏可以進行單元測試,嘲笑仍然是「邏輯免費」,等等。