在Backbone渲染方法中调用jQuery插件

时间:2011-08-18 13:08:18

标签: jquery jquery-plugins backbone.js

我在Backbone中有一个基本上像这样的渲染方法:

render: function () {
  $.tmpl(this.template, attrs).appendTo(this.el);
  return this;
},

从路由器操作调用:

action: function () {
  $('#container').empty();
  $('#container').append(myView.render().el);
},

现在,我想在此视图中的label元素上应用插件。我的第一个想法是在render内调用插件:

render: function () {
  $.tmpl(this.template, attrs).appendTo(this.el);
  this.$('label').inFieldLabels();
  return this;
},

但这不起作用(我假设这是因为该元素尚未添加到DOM中)。如果我在路由器操作中调用插件,它 工作:

action: function () {
  $('#container').empty();
  $('#container').append(myView.render().el);
  myView.$('label').inFieldLabels();
},

我宁愿不这样做,因为插件是视图的一部分,而不是路由器,所以在动作中调用它是没有意义的。有更好的方法吗?

5 个答案:

答案 0 :(得分:5)

贝特这样做:

action: function () {
    var container = $('#container');

    container.empty();
    myView.render(container);
},

render: function (container) {
    $(this.el)
        .append($.tmpl(this.template, attrs))
        .appendTo(container);
    $('label', this.el).inFieldLabels();
    return this;
},

答案 1 :(得分:5)

我遇到了类似的问题,设置了jQuery Tools Tooltip插件。但我有一个非常不同的方法,可以很好地工作:在视图上触发自定义事件。据我所知,Backbone中没有“插入dom”事件,所以我自己就做了。我不使用路由器,但上面修改过的代码看起来像这样:

// In the router:
action: function () {
    var container = $('#container');

    container.append(myView.render().el));
    myView.trigger('rendered');
},

// In the view:
initialize: function() {
    this.bind('rendered', this.afterRender, this);
},
render: function (container) {
    $(this.el).append($.tmpl(this.template, attrs))
    return this;
},
afterRender: function() {
    $('label', this.el).inFieldLabels();
}

我认为优点是视图不知道它的容器。缺点是它就像一行或两行代码。但是如果你需要设置很多插件或做更多需要元素在DOM中的东西,那么它就能很好地工作(并且它会保持逻辑分离)。

我实际上喜欢@ Skilldrick将容器传递给视图的方法,但我仍然觉得让父视图负责插入子视图是有意义的。我是Backbone的新手,所以请随时发表评论。

答案 2 :(得分:2)

我能够通过在渲染函数中指定jQuery的上下文来使我的jQuery插件正常工作:

    render: function () {
    $(this.el).html(this.template(this.model.toJSON()));
    $('#email1dropdown', this.el).dropdownify();

    return this;
},

答案 3 :(得分:0)

我已经通过在我的视图中添加loadPlugins方法解决了这个问题,因此我可以在渲染操作后执行myView.loadPlugins()。它并不理想,但它确实有效。


编辑:好吧,我heard from the horse's mouth看起来在将元素添加到DOM之前我无法应用插件,所以我可以像上面那样做(使用loadPlugins)或者我可以修改代码,以便在render方法中将元素添加到DOM中。希望这有助于处于类似位置的人。

以下是我现在的做法:

//in router
action: function () {
  var myView = new MyView({
    el: '#container'
  });
}

//in view
render: function () {
  $.tmpl(this.template, attrs).appendTo(this.el); //this now appends to the DOM
  this.loadPlugins();
  return this;
},

loadPlugins: function () {
  this.$('label').inFieldLabels();
  //and other plugins
},

答案 4 :(得分:0)

我遇到了类似的问题但在我的情况下,即使上述解决方案也无效,因为父视图尚未添加到DOM中。

坚持让父视图将子项添加到DOM的约定,在render方法中执行loadPlugins()不起作用。

这就是我所做的。这有点像hacky但可以提供帮助,这取决于你在整个层次结构中管理你的观点的方式:

render: function() {
  var self = this;

  setTimeout(function() {
    $(self.el).setupPlugin();
  }, 0);

  return this;
}

使用setTimeout为0允许当前调用堆栈完成,因此在调用超时函数时,视图及其所有父项都已添加到DOM中。 (如果你坚持上述惯例。)