可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am using backbone.js and underscore.js to build an javascript application. Since hours of reading and trying to run a template within a template like below, it is getting more and more frustrating.
My template using the build in underscore.js template engine:
<script id="navigation_template" type="text/template">
<div><%= title %>
<% _.each(children, function(child) { %>
<% render_this_template_recursively(child) %>
<% }); %>
</div>
</script>
I would like to render this template for every child element ( render_this_template_recursively(child) ).
How can I do this?
Thanks
回答1:
I've not personally tried this but _.template returns a function (I've named it templateFn to emphasize that), so you could pass it into the template like this:
var templateFn = _.template($('#navigation_template').html());
$(this.el).html(templateFn({model: this.model, templateFn: templateFn}));
Notice that i'm passing in the whole model (assuming that your model has a children property which is itself a collection of backbone models) and your template would be changed to:
<script id="navigation_template" type="text/template">
<div><%= model.escape('title') %>
<% _.each(model.children, function(child) { %>
<%= templateFn(child, templateFn) %>
<% }); %>
</div>
</script>
Good luck. I hope this works for you
回答2:
I just successfully tried this. I tested it with only pure UnderscoreJS, no BackboneJS but functionally it shouldn't matter.
Here is the code:
<!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>
回答3:
I've tried to use example presented by timDunham and Ates Goral, but it did not work for me, so I've made a little upgrade for it. Find it below.
view:
template: _.template($("#tree").html()),
render: function () {
this.$el.html(this.template({
options: this.collection.toJSON(),
templateFn: this.template
}));
}
and 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>
And it works pretty good for me. The main difference, as you can see, is the passing configuration object into templateFn, instead of arguments. Hope you'll find it useful.
回答4:
A recursive template can look something like this:
<ul>
<% entries.forEach(function (entry) { %>
<li>
<%= entry.title %>
<%
if (entry.children) {
print(tmpl({
entries: entry.children,
tmpl: tmpl
}));
}
%>
</li>
<% }); %>
</ul>
First, pre-compile your template:
entriesTmpl = _.template(entriesTmpl);
Then call it while passing both your data and the template itself:
$el.html(entriesTmpl({
entries: entryTree,
tmpl: entriesTmpl
});
回答5:
I implemented this recently using backbone-relational. I created a fiddle that I thought might be helpful if you want to see a working solution: http://jsfiddle.net/blaisco/ADKrK/
I've posted the relevant bits below.
The view:
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;
}
});
The html/template:
<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>