Best way to asynchronously load underscore templates

耗尽温柔 提交于 2019-12-17 23:30:12

问题


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


回答1:


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



回答2:


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.




回答3:


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)



来源:https://stackoverflow.com/questions/7542089/best-way-to-asynchronously-load-underscore-templates

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