Issue
I need to use the underscore template instead of the default KnockoutJS template engine due to performance. However, since I'm in an asp.net environment the default tags of <%
and %>
will not work because of the asp.net handler.
What I need is to apply something like the following:
_.templateSettings = {
interpolate : /\{\{(.+?)\}\}/g
};
Making it use the {{
and }}
tags
Note 7: Using the Underscore.js template engine
The Underscore.js template engine by default uses ERB-style delimiters (<%= ... %>
). Here’s how the preceding example’s template might look with Underscore:
<script type="text/html" id="peopleList">
<% _.each(people(), function(person) { %>
<li>
<b><%= person.name %></b> is <%= person.age %> years old
</li>
<% }) %>
</script>
Here’s a simple implementation of integrating Underscore templates with Knockout. The integration code is just 16 lines long, but it’s enough to support Knockout data-bind attributes (and hence nested templates) and Knockout binding context variables ($parent, $root, etc.).
If you’re not a fan of the <%= ... %>
delimiters, you can configure the Underscore template engine to use any other delimiter characters of your choice.
Taken from knockoutjs.com
From the above the bold documentation
It states i can change the delimiter but doesn't specify any specifics on how to do it...
Current Attempt
ko.underscoreTemplateEngine = function() {
};
ko.underscoreTemplateEngine.prototype = ko.utils.extend(new ko.templateEngine(), {
renderTemplateSource: function (templateSource, bindingContext, options) {
// Precompile and cache the templates for efficiency
var precompiled = templateSource['data']('precompiled');
if (!precompiled) {
precompiled = _.template("<% with($data) { %> " + templateSource.text() + " <% } %>");
templateSource['data']('precompiled', precompiled);
}
// Run the template and parse its output into an array of DOM elements
var renderedMarkup = precompiled(bindingContext).replace(/\s+/g, " ");
return ko.utils.parseHtmlFragment(renderedMarkup);
},
createJavaScriptEvaluatorBlock: function(script) {
return "<%= " + script + " %>";
}
});
ko.setTemplateEngine(new ko.underscoreTemplateEngine());
Update:
I no longer am using the above I simply include jquery, underscore, and knockout. Then in script
i just have
_.templateSettings = {
interpolate: /\{\{([\s\S]+?)\}\}/g
};
However, nothing is being parsed.
Template declaration is
<script type="text/html" id="common-table-template">
Working Demo jsFiddle
HTML
<h1>People</h1>
<ul data-bind="template: { name: 'peopleList' }"></ul>
<script type="text/html" id="peopleList">
{{ _.each(people(), function(person) { }}
<li>
<b data-bind="text: person.name"></b> is {{= person.age }} years old
</li>
{{ }) }}
</script>
<p>This shows that you can use both Underscore-style evaluation (<%= ... %>) <em>and</em> data-bind attributes in the same templates.</p>
JS
/* ---- Begin integration of Underscore template engine with Knockout. Could go in a separate file of course. ---- */
ko.underscoreTemplateEngine = function () { }
ko.underscoreTemplateEngine.prototype = ko.utils.extend(new ko.templateEngine(), {
renderTemplateSource: function (templateSource, bindingContext, options) {
// Precompile and cache the templates for efficiency
var precompiled = templateSource['data']('precompiled');
if (!precompiled) {
_.templateSettings = {
interpolate: /\{\{=(.+?)\}\}/g,
escape: /\{\{-(.+?)\}\}/g,
evaluate: /\{\{(.+?)\}\}/g
};
precompiled = _.template("{{ with($data) { }} " + templateSource.text() + " {{ } }}");
templateSource['data']('precompiled', precompiled);
}
// Run the template and parse its output into an array of DOM elements
var renderedMarkup = precompiled(bindingContext).replace(/\s+/g, " ");
return ko.utils.parseHtmlFragment(renderedMarkup);
},
createJavaScriptEvaluatorBlock: function(script) {
return "{{= " + script + " }}";
}
});
ko.setTemplateEngine(new ko.underscoreTemplateEngine());
/* ---- End integration of Underscore template engine with Knockout ---- */
var viewModel = {
people: ko.observableArray([
{ name: 'Rod', age: 123 },
{ name: 'Jane', age: 125 },
])
};
ko.applyBindings(viewModel);
You're asking how to change Underscore's delimiter characters? This SO answer seems to have the right answer. Basically, you can define your own regex for nesting data:
_.template("hello <?= name ?>", {"name": "Mike"}, {"interpolate": /<?=([\s\S]+?)%>/g) ?>})
A couple of side notes:
You say you're using Underscore, instead of Knockout's native template engine, for performance reasons. As an avid Knockout user, this sounds fishy. Knockout's native template engine is very fast and ultimately tested far more than 3rd party engines plugged into Knockout. I've built numerous applications with KO and never had an issue with the template engine being too slow. Make sure you really need to use Underscore. For the vast majority of cases, Knockout's native template engine works perfectly fine.
Secondly, are you aware of the Razor syntax? This wouldn't interfere with Underscore.
The _.templateSettings
configuration is global, so just add the block
_.templateSettings = {
interpolate : /\{\{(.+?)\}\}/g
};
anywhere earlier in your code.
来源:https://stackoverflow.com/questions/18410055/using-underscore-template-with-knockout-using-interpolate-due-to-asp-net