使用Backbone进行异步模板加载和后渲染操作

Aka*_*sha 3 javascript jquery backbone.js backbone-boilerplate

我正在使用骨干样板来渲染我的模板,它的fetchTemplate方法缓存渲染的模板.

我想在渲染的内容上运行一些额外的代码,比如初始化手风琴等,但是使用异步编译模板执行此操作比我想象的要复杂得多.

这是一个例子:

Duel.Views.Home = Backbone.View.extend({
  template: "/templates/duel_home.jade",
  render: function() {
    var view = this;
    statusapp.fetchTemplate(this.template, function(tmpl) {
      $(view.el).html( tmpl({duels: view.collection.toJSON()}) );
      view.postrender();
    });
    return this;
  },
  postrender: function() {
    $('#duel-new').each(function() {
      console.log('Found something')
    });
  }
});
Run Code Online (Sandbox Code Playgroud)

除此之外,我使用http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/中概述的视图处理程序.

我这样做了

var view = Duel.Views.Home({model: mymodel})
viewHandler('#content').showView(view)
Run Code Online (Sandbox Code Playgroud)

这个电话

$('#content').html(view.render().el)
Run Code Online (Sandbox Code Playgroud)

但是,当模板尚未缓存时,首先调用render,然后按时调用postrender.另一方面,当模板已经被缓存时,模板立即呈现,后期调用被调用,但view.el尚未插入到DOM中,因此$(this.el)是一个空列表,而$('#duel -new').each()是"无效的".

当然,我可以在viewHandler的render调用之后添加postrender方法,但这会导致同样的问题,但是在第一次调用render方法时.由于模板尚未编译,因此在其元素存在之前调用postrender,因此不能在这些不存在的元素上定义处理程序.

关于如何正确克服这个问题的任何想法?例如,对于使用.on的简单点击事件来说,这是相对简单的,但是更一般的结构$('#tabs').tabs()呢,例如?

我的fetchTemplate函数如下:

fetchTemplate: function(path, done) {
  window.JST = window.JST || {};

  // Should be an instant synchronous way of getting the template, if it
  // exists in the JST object.
  if (JST[path]) {
    return done(JST[path]);
  }

  // Fetch it asynchronously if not available from JST
  return $.get(path, function(contents) {
    var tmpl = jade.compile(contents,{other: "locals"});
    JST[path] = tmpl;

    return done(tmpl);
  });
},
Run Code Online (Sandbox Code Playgroud)

ggo*_*zad 5

不需要所有这些并发症.

原始fetchTemplate返回一个jQuery 承诺.你的版本也应该如此,如果你不了解jQuery的Deferreds和Promises,那么现在是看它们的好时机.回调已经死了;)

使用promises,一切都变得如此简单:在你的initializedo中获取模板并分配promise.然后仅在履行承诺时呈现,例如:

Duel.Views.Home = Backbone.View.extend({
    initialize: function () {
       this.templateFetched = statusapp.fetchTemplate(this.template);

    },
    ...

    render: function () {
        var view = this;
        this.templateFetched.done(function (tmpl) {
            view.$el.html( tmpl({duels: view.collection.toJSON()}) );
            ... // All your UI extras here...
        });
    }
});
Run Code Online (Sandbox Code Playgroud)

请注意,一旦履行承诺,done将始终立即运行.如果您在视图$el外修改视图,即包装代码,您当然可以遵循相同的模式view.templatedFetched.done(...).