异步加载下划线模板的最佳方法

时间:2011-09-24 21:36:13

标签: javascript backbone.js underscore.js

我打算使用backbone.js和underscore.js来创建网站,我将有很多下划线模板:

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

当然我的模板会复杂得多。

因为我会有很多,所以每次页面加载时我都不想加载所有模板。我想找到一个解决方案,我只能在使用时加载特定的模板。

另一件事是我的大多数模板都具有相同的结构,只有<p id="form"></p><p id="dynamic_date"></p>内容会有所不同。

你能告诉我怎么办?

谢谢,

3 个答案:

答案 0 :(得分:8)

编辑:我做了一些研究并移植了我的iCanHaz代码以强调它还使用localStorage

这是一个github存储库:https://github.com/Gazler/Underscore-Template-Loader

代码是:

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

调用它看起来像:

      templateLoader.loadRemoteTemplate("test_template", "templates/test_template.txt", function(data) {
        var compiled = _.template(data);
        $('#content').html(compiled({name : 'world'}));
      });

这是我的原始答案

这是我为ICanHaz(小胡子)写的一个方法,它出于同样的原因执行这个确切的函数。

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

然后我这样称呼它:

ich.loadRemoteTemplate(page+'_page', function() {
  $('#'+page+'_page').html(ich[page+'_page_template']({}, true));
});

答案 1 :(得分:3)

我非常喜欢stackoverflow团队使用mvc-miniprofiler进行模板测试的方式。看看这些链接:

Includes.jsGithub link

Includes.tmplGithub link

如果您的浏览器支持本地存储,他们会使用本地存储在本地缓存模板。如果不是,他们每次只加载它。它是处理模板的一种非常流畅的方式。这也允许您将不需要的模板立即保存在单独的文件中,而不会使您的HTML混乱。

祝你好运。

答案 2 :(得分:2)

虽然上述两个答案都有效,但我发现以下是一个更简单的方法。

将包含在脚本标记中的模板放入文件(例如“templates.html”)中,如下所示:

<script type="text/template" id="template-1">
  <%- text %>
</script>

<script type="text/template" id="template-2">
  oh hai!
</script>

接下来的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");
  });
});

然后,您可以使用之前定义的ID轻松选择模板。我添加了承诺

$.when(templatesLoadedPromise).then(function() {
  _.template($('#template-1').html(), {'text':'hello world'} )
});

如果需要,您可以扩展它并加载多个文件。

作为旁注,我发现初始页面渲染所需的任何核心模板​​都可以更好地嵌入到HTML中(我在服务器上使用龙卷风模块),但上述方法对于以后需要的任何模板都能很好地工作(例如,在我的情况下,我希望跨页面使用的注册小部件的模板是完美的,因为它只会加载到用户交互并且不是页面的核心)