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

标签 javascript jquery backbone.js backbone-boilerplate

我正在使用 Backbone 样板来呈现我的模板,它的 fetchTemplate 方法缓存呈现的模板。

我想在呈现的内容上运行一些额外的代码,例如初始化 Accordion 等,但是使用异步编译模板执行此操作比我想象的更棘手。

这是一个例子:

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

除上述之外,我还使用了 View 处理程序,如 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)

这个调用

$('#content').html(view.render().el)

但是发生的事情是,当模板还没有被缓存时,先调用render,然后准时调用postrender。另一方面,当模板已经被缓存时,模板立即被渲染,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);
  });
},

最佳答案

不需要所有这些并发症。

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

使用 promises,一切都变得如此简单: 在您的 initialize 中获取模板并分配 promise 。然后仅在 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...
        });
    }
});

请注意,一旦 promise 得到履行,done 将始终简单地立即运行。 如果您在 View 外修改 View $el,当然可以遵循相同的模式,即将代码包装在 view.templatedFetched.done(...) 中。

关于javascript - 使用 Backbone 进行异步模板加载和渲染后操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10398997/

相关文章:

javascript - 如何在 Backbone.js 应用程序中使用 jQuery Multiselect 插件?

javascript - 使用 id 时如何使用 Sequelize 创建关联?

jquery - 使用jquery执行border :none and background-color:white on empty cells

javascript - 如何对不同属性执行自定义主干排序?

javascript - 我还应该将我的数据保存在 Javascript 数据结构中吗?或者只是在 DOM 中?

php - 社交网络墙发布逻辑不起作用

backbone.js - 在backbone.js 中创建向导流程

javascript - 如何生成多个response.write :s with json in node. js/express?

javascript - 如何读取指针(local_tbb.dwData)处的内存以获取窗口句柄

javascript - Gson.fromJson 卡在线上