【问题标题】:loading handlebars template asynchronously异步加载车把模板
【发布时间】:2014-08-10 22:13:54
【问题描述】:

我正在尝试编写一个函数,该函数将为我提供一个已编译的车把模板(我的所有模板都在单独的文件中),使用 ajax 调用来获取模板并编译它以供使用,但我需要使用一个 Promise所以我可以实际使用它。

function getTemplate(name){
    $.get('/'+name+'.hbs').success(function(src){
       var template = Handlebars.compile(src);
       //can't return the template here.
    });
}

我如何使用 Promise 做到这一点,以便我可以执行以下操作:

$("a").click(function(e){
    getTemplate('form').done(function(template){
       $("body").append(template({
               name: "My Name"
           })
       );
    });
});

【问题讨论】:

  • @PedroFerreira async:false 已被弃用,这是一个糟糕的解决方案
  • @charlietfl 是的,我同意。但在特定情况下,作为一种选择,它可能仍然很有趣。
  • @PedroFerreira 有很多方法可以避免使用它。请注意,您提供的链接已有 5 年历史
  • @charlietfl 我不提倡使用async: false。我只是简单地提到它与这个讨论和一个可能的(虽然通常很糟糕,我同意)解决方案有关。我并不是建议 OP 使用它,否则我会将其发布为答案。

标签: jquery handlebars.js promise


【解决方案1】:

Chovy,我看到你已经接受了一个答案,但你可能有兴趣知道 getTemplate 可以通过链接 .then() 而不是 .success() 几乎像问题中一样写成:

function getTemplate(name) {
    return $.get('/'+name+'.hbs').then(function(src) {
       return Handlebars.compile(src);
    });
}

或者,采用charlietfl的思路,传入数据,返回一个完全组合片段的Promise:

function getTemplate(name, data) {
    return $.get('/'+name+'.hbs').then(function(src) {
       return Handlebars.compile(src)(data);
    });
}

nett 效果与 charlietfl 的 getTemplate 版本相同,但 .then() 无需显式创建 Deferred。代码因此更加紧凑。

【讨论】:

  • 感谢您接受 Chovy,虽然我宁愿觉得我偷走了查理的代表 :-|
  • 不要忘记 ajax 是异步的,您可能应该在该函数中使用回调来确保您没有问题。使用此代码并遇到了这个确切的问题
  • 啊,刚刚注意到他在实际的函数调用中使用了 .done ... doh!
【解决方案2】:

以下将数据参数添加到getTemplate 函数以及模板名称。

$(function(){
  var postData={title: "My New Post", content: "This is my first post!"};
 getTemplate('template-1',postData).done(function(data){
   $('body').append(data)
 })
});

function getTemplate( name,data){
  var d=$.Deferred();

  $.get(name+'.html',function(response){

    var template = Handlebars.compile(response);
    d.resolve(template(data))
  });

  return d.promise();

}

DEMO

【讨论】:

    【解决方案3】:

    我创建了一个库来帮助解决此类问题,请查看github

    您只需将其添加到您的主应用视图中:

    <script type="text/x-handlebars" data-template-name="application">
        <!-- Your HTML code -->
        <div class="container">
            <div class="modal fade" id="editView" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
                <div class="modal-dialog">
                    <div class="modal-content">
                        {{view MainApp.ModalContainerView elementId="modalContainerView"}}
                    </div><!-- /.modal-content -->
                </div><!-- /.modal-dialog -->
            </div><!-- modal edit dialog -->
            {{view MainApp.AppContainerView elementId="appContainerView"}}
            {{outlet}}
        </div> <!-- main container -->
    </script>
    

    把它放到你的 MainApp 中

    var MainApp = Em.Application.create({
        LOG_TRANSITIONS: true,
        ready: function () {
        /** your code **/
        MainApp.AppContainerView = Em.ContainerView.extend({});
        MainApp.ModalContainerView = Em.ContainerView.extend({});
        /** And other containerView if you need for sections in tabs **/
        });
    

    例如,要使用所需模板打开模态框,您只需:

    FactoryController.loadModalTemplate(templateName, callback);
    

    别忘了添加 FactoryController 和 RepositoryController

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-29
      • 1970-01-01
      • 2012-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-13
      相关资源
      最近更新 更多