Best way to asynchronously load underscore templates

前端 未结 3 1744
别跟我提以往
别跟我提以往 2020-12-13 22:40

I\'m planning to use backbone.js and underscore.js for creating website, and I will have lots of underscore templates:



        
相关标签:
3条回答
  • 2020-12-13 22:50

    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.

    0 讨论(0)
  • 2020-12-13 22:51

    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)

    0 讨论(0)
  • 2020-12-13 22:56

    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));
    });
    
    0 讨论(0)
提交回复
热议问题