2011-11-09 44 views
17

我正在使用backbone.js和underscore.js來構建一個JavaScript應用程序。自從閱讀並嘗試在下面的模板中運行模板幾個小時後,它越來越令人沮喪。在模板(遞歸)中運行模板在underscore.js模板引擎中

我在underscore.js模板引擎使用構建模板:

<script id="navigation_template" type="text/template"> 
    <div><%= title %> 
     <% _.each(children, function(child) { %> 
      <% render_this_template_recursively(child) %> 
     <% }); %> 
    </div> 
</script> 

我想使這個模板爲每個子元素(render_this_template_recursively(子))。

我該怎麼做?

感謝

+1

heeeeey,這是一個很有趣的問題...你試試下面的答案嗎? ;) –

+1

嘿亞當,你解決了嗎?還是你用別的東西? –

+1

@ jamie-wilson我從Ashish Datta的回答中得到了一些啓發。我在下面發佈了一個簡約的例子。 –

回答

34

我沒有親自試過,但_.template返回函數(我把它命名爲templateFn強調的),所以你可以把它傳遞到模板是這樣的:

var templateFn = _.template($('#navigation_template').html()); 

$(this.el).html(templateFn({model: this.model, templateFn: templateFn})); 

注意到,我傳遞整個模型(假設你的模式有一個孩子財產本身骨幹機型的集合),你的模板將被更改爲:

<script id="navigation_template" type="text/template"> 
    <div><%= model.escape('title') %> 
     <% _.each(model.children, function(child) { %> 
      <%= templateFn(child, templateFn) %> 
     <% }); %> 
    </div> 
</script> 

祝你好運。我希望這適用於你

+0

謝謝!很好的回答 –

+0

@timDunham如果我使用文本插件來加載模板,我應該怎麼做。我應該做templateFn = _.template($('#navigation_template')。html()); – asdfdefsad

+0

'<%= templateFn(child,templateFn)%>'不適合我。但完美的作品'<%= templateFn({model:child,templateFn:templateFn})%>' – Londeren

8

我剛剛成功地嘗試過這一點。我用純粹的UnderscoreJS測試它,沒有BackboneJS,但功能上它應該沒關係。

下面是代碼:

<!DOCTYPE html> 
<html lang="en"> 
    <head> 
    <meta charset="utf-8"> 
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> 
    <script type="text/javascript" src="underscore.js"></script>  
<style> 

.container { 
    position: relative; 
    margin-bottom: 20px; 
} 

#container { 
    position: relative; 
    margin: auto; 
} 

.fib-box { 
    position: absolute; 
    top: 0px; 
    left: 0px; 
    background: rgba(0,68,242,0.15); 
    border: 1px solid rgba(0,0,0,0.20); 
} 

.header { 
    padding-bottom: 10px; 
} 

</style> 
    </head> 
    <body> 

    <div class="header"> 
     <h3>Render Fibonacci With UnderscoreJS</h3> 
     <form id="updateCount"> 
      <input type="text" value="13" id="fibSequence" /> 
      <input type="submit" value="Update" /> 
     </form> 
    </div> 

    <div class="container"> 
    <div id="container"> 

    </div>  
    </div> 

<script type="text/template" id="template"> 
<% if(depth){ %> 
<div class='fib-box' data-depth='<%= depth %>' style='width: <%= val %>px; height: <%= val %>px;'></div> 
<% print(template(getFibObj(depth-1))) %> 
<% } %> 
</script> 

<script type="text/javascript"> 

var template; 

$(document).ready(function(){ 

    template = _.template($("#template").text()); 

    $("#updateCount").submit(function(){ 

     $("#container").html(template(getFibObj($("#fibSequence").val()))); 

     var width = $("#container .fib-box:first").css("width"); 
     $("#container").css({width: width, 'min-height': width}); 

     return false; 
    }); 

    $("#updateCount").submit(); 
}); 

function getFibObj(i){ 
    return {depth: i, val: fib(i)}; 
} 

function fib(i){ 
    return (i == 0 || i == 1) ? i : fib(i-1) + fib(i-2); 
} 

</script> 

    </body> 
</html> 
+2

在演示代碼上幹得不錯! –

+0

@Ashish Datta是否有可能對viewmodel類的東西使用這種方法。像數據處理應該在viewmodel中完成,然後將它傳遞給每個遞歸的模板。 – asdfdefsad

+0

@JSBin不確定我是否遵循100%,但是您可以在控制器中建立HTML塊,然後將所有這些傳遞到您的模板中? –

1

遞歸模板可以是這個樣子:

<ul> 
    <% entries.forEach(function (entry) { %> 
    <li> 
     <%= entry.title %> 
     <% 
     if (entry.children) { 
      print(tmpl({ 
       entries: entry.children, 
       tmpl: tmpl 
      })); 
     } 
     %> 
    </li> 
    <% }); %> 
</ul> 

首先,預編譯模板:

entriesTmpl = _.template(entriesTmpl); 

然後調用它同時傳遞數據和模板本身:

$el.html(entriesTmpl({ 
    entries: entryTree, 
    tmpl: entriesTmpl 
}); 
5

我試過使用timDunham和Ates Goral提供的例子,但它並沒有爲我工作,所以我已經爲它做了一點升級。在下面找到它。

觀點:

template: _.template($("#tree").html()), 

    render: function() { 
     this.$el.html(this.template({ 
      options: this.collection.toJSON(), 
      templateFn: this.template 
     })); 
    } 

和模板:

<script type="text/template" id="tree"> 
<ul> 
    <% _.each(options, function (node) { %> 
     <li><%= node.title %></li> 
     <% if (node.children) { %> 
      <%= templateFn({ options: node.children, templateFn: templateFn }) %> 
     <% } %> 
    <% }); %> 
</ul> 

而且它非常適合我。正如你所看到的,主要區別是將配置對象傳遞給templateFn,而不是參數。希望你會發現它有用。

+0

是否有可能使用這種方法與viewmodel類的東西。像數據處理應該在viewmodel中完成,然後將其傳遞給每個遞歸的模板 – asdfdefsad

0

我最近使用骨幹關係實現了這個功能。我創建了一個小提琴,如果你想看到一個可行的解決方案,我認爲它可能會有幫助:http://jsfiddle.net/blaisco/ADKrK/

我已經發布了下面的相關位。

的觀點:

var FolderView = Backbone.View.extend({ 
    el: $("#main"), 

    template: _.template($("#folder-tmpl").html()), 

    render: function() { 
     this.$el.html(this.template({ 
      "folder": parentFolder.toJSON(), 
      "templateFn": this.template 
     })); 
     return this; 
    } 
}); 

的HTML /模板:

<ul id="main"></ul> 

<script type="text/template" id="folder-tmpl"> 
    <li> 
     <a href="#" class="folder"><%= folder.title %></a> 
     <% if(folder.children.length) { %><ul><% } %> 
     <% _.each(folder.children, function(child) { %> 
      <%= templateFn({"folder": child, "templateFn": templateFn}) %> 
     <% }); %> 
     <% if(folder.children.length) { %></ul><% } %> 
    </li> 
</script> 
+0

是否有可能對viewmodel類的東西使用這種方法。像數據處理應該在viewmodel中完成,然後將其傳遞給每個遞歸的模板 – asdfdefsad