templateSettings not working

2020-02-01 02:23发布

问题:

I get a compilation error at runtime when I attempt to render the following template:

 <script id="tmpl-books" type="text/template">
        <% _.each(items, function(item) { %>
            <ul>
                <li>Title: <%= item.title %></li>
                <li>Author: <%= item.author %></li>
            </ul>
        <% }); %>

    </script>

<script type="text/javascript">
      _.templateSettings = {
                evaluate: /\{\{=(.+?)\}\}/g,
                interpolate: /\{\{(.+?)\}\}/g,
                escape: /\{\{-(.+?)\}\}/g
            };

            var list =
            {
                items:
                [
                    { "title": "Myst: The Book of Atrus", "author": "Rand Miller" },
                    { "title": "The Hobbit", "author": "J.R.R. Tolkien" },
                    { "title": "Stardust", "author": "Neil Gaiman" }]
            };
            $(document).ready(function () {


                var tmplMarkup = $('#tmpl-books').html();
                // ...tell Underscore to render the template...
                var compiledTmpl = _.template(tmplMarkup, list);
                // ...and update part of your page:
                $('#rendered').append(compiledTmpl);
            });
</script>

回答1:

You have two problems:

  1. Your templateSettings regexes overlap in a bad way.
  2. Your templateSettings don't match your template.

The documentation isn't explicit about what order the regexes are applied in but the source code is:

var matcher = new RegExp([
  (settings.escape || noMatch).source,
  (settings.interpolate || noMatch).source,
  (settings.evaluate || noMatch).source
].join('|') + '|$', 'g');

In particular, interpolate will be matched before evaluate. Your interpolate is looking for things like {{ ... }} so it will pick up things like {{= ... }} before your evaluate regex can see them. The result will be stray = in the generated source code. So your interpolate regex can't match things that your evaluate will be looking for. You probably want to use these regexes:

_.templateSettings = {
    evaluate: /\{\{(.+?)\}\}/g,
    interpolate: /\{\{=(.+?)\}\}/g,
    escape: /\{\{-(.+?)\}\}/g
};

Note that I've switched who looks for {{= ... }} and {{ ... }}.

Then your template needs to use the Mustache-style delimiters rather than the default Underscore ones:

<script id="tmpl-books" type="text/template">
    {{ _.each(items, function(item) { }}
        <ul>
            <li>Title: {{= item.title }}</li>
            <li>Author: {{= item.author }}</li>
        </ul>
    {{ }); }}
</script>

Fixing those two issues should make things work.

Demo: http://jsfiddle.net/ambiguous/my49N/