I'm planning to use backbone.js and underscore.js for creating website, and I will have lots of underscore templates:
<script type="text/template" id="search_template">
<p id="header">
//header content will go here
</p>
<p id="form">
<label>Search</label>
<input type="text" id="search_input" />
<input type="button" id="search_button" value="Search" 开发者_JAVA技巧/>
</p>
<p id="dynamic_date">
//dynamic data will be displayed here
</p>
</script>
Of course my templates will be much more complicated.
Since I will have lots of them, I don't want to load all templates every time when page loads. I want to find a solution, where I can load specific template only when it will be used.
Another thing is that most of my templates will have same structure, only <p id="form"></p>
and <p id="dynamic_date"></p>
content will differ.
Could you please suggest me how should I do it?
Thanks,
Edit: I did some research and ported my iCanHaz code to underscore it also uses localStorage is available
Here is a github repository: https://github.com/Gazler/Underscore-Template-Loader
The code is:
(function() {
var templateLoader = {
templateVersion: "0.0.1",
templates: {},
loadRemoteTemplate: function(templateName, filename, callback) {
if (!this.templates[templateName]) {
var self = this;
jQuery.get(filename, function(data) {
self.addTemplate(templateName, data);
self.saveLocalTemplates();
callback(data);
});
}
else {
callback(this.templates[templateName]);
}
},
addTemplate: function(templateName, data) {
this.templates[templateName] = data;
},
localStorageAvailable: function() {
try {
return 'localStorage' in window && window['localStorage'] !== null;
} catch (e) {
return false;
}
},
saveLocalTemplates: function() {
if (this.localStorageAvailable) {
localStorage.setItem("templates", JSON.stringify(this.templates));
localStorage.setItem("templateVersion", this.templateVersion);
}
},
loadLocalTemplates: function() {
if (this.localStorageAvailable) {
var templateVersion = localStorage.getItem("templateVersion");
if (templateVersion && templateVersion == this.templateVersion) {
var templates = localStorage.getItem("templates");
if (templates) {
templates = JSON.parse(templates);
for (var x in templates) {
if (!this.templates[x]) {
this.addTemplate(x, templates[x]);
}
}
}
}
else {
localStorage.removeItem("templates");
localStorage.removeItem("templateVersion");
}
}
}
};
templateLoader.loadLocalTemplates();
window.templateLoader = templateLoader;
})();
Calling it would look something like:
templateLoader.loadRemoteTemplate("test_template", "templates/test_template.txt", function(data) {
var compiled = _.template(data);
$('#content').html(compiled({name : 'world'}));
});
Here is my original answer
Here is a method I wrote for ICanHaz (mustache) that performs this exact function for the same reason.
window.ich.loadRemoteTemplate = function(name, callback) {
if (!ich.templates[name+"_template"]) {
jQuery.get("templates/"+name+".mustache", function(data) {
window.ich.addTemplate(name+"_template", data);
callback();
});
}
else {
callback();
}
}
I then call it like so:
ich.loadRemoteTemplate(page+'_page', function() {
$('#'+page+'_page').html(ich[page+'_page_template']({}, true));
});
I really like the way the stackoverflow team has done templating with the mvc-miniprofiler. Take a look at these links:
Includes.js (Github link)
Includes.tmpl (Github link)
They use the local storage to cache the templates locally if your browser supports local storage. If not they just load it every time. Its a pretty slick way to handle the templates. This also allows you to keep your templates that aren't required immediately in a separate file and not clutter up your html.
Good luck.
Although both of the above answers work, I found the following to be a much simpler approach.
Places your templates wrapped in script tags into a file (say "templates.html") as follows:
<script type="text/template" id="template-1">
<%- text %>
</script>
<script type="text/template" id="template-2">
oh hai!
</script>
Then the following bit of javascript:
$(document).ready(function() {
url ='http://some.domain/templates.html'
templatesLoadedPromise = $.get(url).then(function(data) {
$('body').append(data)
console.log("Async loading of templates complete");
}).fail(function() {
console.log("ERROR: Could not load base templates");
});
});
Which then let's you select your templates quite simply using the IDs you previously defined. I added the promise
$.when(templatesLoadedPromise).then(function() {
_.template($('#template-1').html(), {'text':'hello world'} )
});
You can then extend this and load multiple files if you want.
As a side note, I've found that any core templates needed for initial page render are better embedded in the HTML (I use tornado modules on the server) but that the above approach works very nicely for any templates needed later (e.g., in my case the templates for a registration widget which I want to use across pages is perfect for this as it'll only be loaded on user interaction and is non-core to the page)
精彩评论