【问题标题】:Best way to asynchronously load underscore templates异步加载下划线模板的最佳方式
【发布时间】:2011-09-24 21:36:12
【问题描述】:

我打算用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>

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

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

另一件事是我的大部分模板都具有相同的结构,只有 &lt;p id="form"&gt;&lt;/p&gt;&lt;p id="dynamic_date"&gt;&lt;/p&gt; 的内容会有所不同。

你能建议我怎么做吗?

谢谢,

【问题讨论】:

    标签: javascript backbone.js underscore.js


    【解决方案1】:

    编辑:我做了一些研究并移植了我的 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));
    });
    

    【讨论】:

    • 你为什么使用 setimeout 并导致 2 秒的延迟?除此之外,很好的答案!
    • @Derick Bailey,哎呀,我昨晚睡觉前完全从我的 github 存储库中复制并粘贴了这个。那纯粹是为了可视化预加载的模板和动态加载的模板之间的区别。感谢您指出这一点。
    • @Gazler,感谢您的回复。我还没有时间查看代码,但我认为这是非常好的解决方案。正如我所见,ICanHaz 适用于小胡子,我想知道它是否也适用于下划线?模板看起来一样...
    • @user616822 当您发布该回复时,我实际上正在创建一个答案。就个人而言,我更喜欢 mustache 和 ICanHaz,但我添加的代码应该可以满足您的需求。 ICanHaz 只是为小胡子提供便利,不适用于下划线模板。希望这会有所帮助。
    • @Gazler,太棒了。我只是试图在我的本地主机上运行它并且它有效。现在我需要弄清楚如何在我的网站上实现它。我也对 localStorage 的想法感兴趣,但我知道我想集中精力让它工作,然后实现 localStorage。您认为我应该现在整合它,还是以后再整合?
    【解决方案2】:

    我真的很喜欢 stackoverflow 团队使用 mvc-miniprofiler 进行模板化的方式。看看这些链接:

    Includes.js (Github link)

    Includes.tmpl (Github link)

    如果您的浏览器支持本地存储,它们会使用本地存储在本地缓存模板。如果不是,他们只是每次都加载它。它是处理模板的一种非常巧妙的方式。这还允许您将不需要立即使用的模板保存在单独的文件中,并且不会弄乱您的 html。

    祝你好运。

    【讨论】:

    【解决方案3】:

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

    将包含在脚本标签中的模板放入文件(例如“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 中(我在服务器上使用 tornado 模块),但上述方法对于以后需要的任何模板都非常有效(例如,在我的情况下,我想跨页面使用的注册小部件的模板非常适合这一点,因为它只会在用户交互时加载并且不是页面的核心)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-06
      • 2012-09-15
      • 1970-01-01
      相关资源
      最近更新 更多