2011-11-09 27 views
17

Tôi đang sử dụng backbone.js và underscore.js để xây dựng một ứng dụng javascript. Kể từ giờ đọc và cố gắng để chạy một mẫu trong một mẫu như dưới đây, nó nhận được càng nhiều bực bội.Chạy Mẫu trong Bản mẫu (đệ quy) trong công cụ mẫu underscore.js

mẫu của tôi bằng cách sử dụng xây dựng trong mẫu động cơ underscore.js:

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

Tôi muốn làm cho mẫu này cho mọi phần tử con (render_this_template_recursively (trẻ em)).

Tôi làm cách nào để thực hiện việc này?

Cảm ơn

+1

heeeeey, đó là khá một câu hỏi thú vị ... bạn đã thử các câu trả lời dưới đây? ;) –

+1

Xin chào Adam, bạn đã làm việc đó chưa? Hay bạn đã sử dụng cái gì khác? –

+1

@ jamie-wilson Tôi có một cái gì đó làm việc với cảm hứng từ câu trả lời của Ashish Datta. Tôi đã đăng một ví dụ tối giản dưới đây. –

Trả lời

34

Tôi đã không cố gắng cá nhân này nhưng _.template trả về một chức năng (tôi đã đặt tên nó là templateFn nhấn mạnh rằng), vì vậy bạn có thể vượt qua nó vào template như thế này:

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

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

ý rằng tôi đang đi qua trong toàn bộ mô hình (giả định rằng mô hình của bạn có một tài sản trẻ em mà là chính nó một bộ sưu tập các mô hình xương sống) và mẫu của bạn sẽ được thay đổi để:

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

Chúc may mắn. Tôi hy vọng điều này phù hợp với bạn

+0

Cảm ơn! câu trả lời tuyệt vời –

+0

@timDunham tôi nên làm gì nếu tôi đang sử dụng plugin văn bản để tải mẫu. tôi nên làm templateFn = _.template ($ ('# navigation_template'). html()); – asdfdefsad

+0

'<% = templateFn (con, templateFn)%>' không hoạt động đối với tôi. Nhưng hoạt động hoàn hảo '<% = templateFn ({model: child, templateFn: templateFn})%>' – Londeren

8

Tôi vừa thử thành công việc này. Tôi đã thử nghiệm nó với chỉ UnderscoreJS thuần túy, không có BackboneJS nhưng chức năng nó không quan trọng.

Đây là mã:

<!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

Công việc tuyệt vời trên mã demo! –

+0

@Ashish Datta là nó có thể sử dụng cách tiếp cận này với loại điều viewmodel. như xử lý dữ liệu nên được thực hiện trong viewmodel và sau đó vượt qua nó để mẫu cho mỗi đệ quy – asdfdefsad

+0

@ JSBin không chắc chắn tôi làm theo 100% nhưng bạn chắc chắn có thể xây dựng các khối HTML trong bộ điều khiển của bạn và sau đó chỉ cần vượt qua tất cả điều đó vào mẫu của bạn? –

1

Mẫu đệ quy có thể trông giống như thế này:

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

Thứ nhất, trước khi biên dịch mẫu của bạn:

entriesTmpl = _.template(entriesTmpl); 

Sau đó gọi nó là trong khi chuyển cả dữ liệu của bạn và bản thân mẫu:

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

Tôi đã cố gắng sử dụng ví dụ được trình bày bởi timDunham và Ates Goral, nhưng nó không hoạt động cho tôi, vì vậy tôi đã nâng cấp một chút cho nó. Tìm nó bên dưới.

xem:

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

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

và mẫu:

<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> 

Và nó hoạt động khá tốt đối với tôi. Sự khác biệt chính, như bạn có thể thấy, là đối tượng cấu hình truyền vào templateFn, thay vì đối số. Hy vọng bạn sẽ thấy nó hữu ích.

+0

là nó có thể sử dụng cách tiếp cận này với loại điều viewmodel. như xử lý dữ liệu nên được thực hiện trong viewmodel và sau đó vượt qua nó để mẫu cho mỗi đệ quy – asdfdefsad

0

Tôi đã triển khai gần đây bằng cách sử dụng quan hệ xương sống. Tôi đã tạo ra một câu đố mà tôi nghĩ có thể hữu ích nếu bạn muốn xem giải pháp làm việc: http://jsfiddle.net/blaisco/ADKrK/

Tôi đã đăng các bit liên quan bên dưới.

Quan điểm:

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; 
    } 
}); 

Các html/mẫu:

<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

là nó có thể sử dụng phương pháp này với loại điều viewmodel. như xử lý dữ liệu nên được thực hiện trong viewmodel và sau đó chuyển nó vào mẫu cho mỗi đệ quy – asdfdefsad

Các vấn đề liên quan