Using Underscore Template with Knockout using interpolate due to asp.net

我与影子孤独终老i 提交于 2019-11-28 05:47:33

问题


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.

Working jsFiddle

Not Working jsFiddle

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

回答1:


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



回答2:


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.




回答3:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!