Backbone:View事件触发多次

时间:2015-02-24 16:45:35

标签: javascript backbone.js

我是Backbone的新手。 我想显示一个库存清单,用户可以从列表中打开任何库存并更改库存值。之后,整个列表应刷新以显示更改的值。

因此,我发现最好不仅要创建集合,还要创建集合和库存模型列表。

为此,我为主表和库存模型视图创建了一个库存集合视图,用于向表中添加行,其中每行是单个模型。

所以这是一个集合视图:

App.Views.StockTable = Backbone.View.extend({ ... initialize: function() { this.render(); }, render: function() { this.$el.html(this.template(this.collection)); this.addAll(); return this; }, addOne: function(stock) { var row = new App.Views.StockRow({ model: stock, suppliers: this.suppliers }); return this; }, addAll: function() { var suppliers = new App.Collections.Suppliers(); var that = this; suppliers.fetch({ success: function() { _.each(that.collection.toJSON(), that.addOne, that); } }); return this; } });

这是我的股票行视图:

App.Views.StockRow = Backbone.View.extend({ el: 'tbody', templateRow: _.template($('#stockRow').html()), templatePreview: _.template($('#stockPreview').html()), events: { 'click #open': 'open' ... }, initialize: function() { this.render(); }, render: function() { this.$el.append(this.templateRow(this.model)) .append(this.templatePreview({ stock: this.model, suppliers: this.suppliers })); return this; }, open: function(e) { var element = $(e.currentTarget); element.attr('id', 'hide'); $('#stock' + element.data('id')).slideToggle('fast'); } ... });

我只写了一段代码。问题是,当我点击'#open'时,该事件会多次触发(正确的是集合中的数量元素)。因此,当我捕获e.currentTarget时,有许多类似的对象。 我做错了什么?

1 个答案:

答案 0 :(得分:0)

我怀疑你有很多事情要发生。

如果没有看到您的模板,我怀疑您的每个StockRow行都会使用id="open"呈现标记。由于id值应该是唯一的,因此请在链接中使用一个类(例如:class="open"),然后在点击处理程序中引用该类:

events: {
  'click .open': 'open'
}

接下来,由于StockRow的每个实例都已经有一个与之关联的model实例,因此只需使用this.model而不是尝试从data中查找它currentTarget的属性。

open: function () {
  $('#stock' + this.model.id).slideToggle('fast');
}

但是,再次,不要在模板中使用id="stock"属性,而是使用类...说class="stock-preview"。然后在你的公开场合寻找...

open: function () {
  this.$el.find('.stock-preview').slideToggle('fast');
}

另一件看起来有问题的是this.addAll();视图的render方法中对StockTable的调用。最佳做法是让渲染方法呈现状态,而不是让它触发ajax调用以获取状态。

例如,在初始化中,您可以设置一些对您的集合更改状态做出反应的事件处理程序(下面是一个不完整的示例,只是希望让您朝着正确的方向前进):

initialize: function (options) {
  …
  _.bindAll(this, 'render', 'renderRow');
  this.collection.on('add', this.renderRow);
  this.collection.on('reset', this.render);
},

render: function () {
  this.$el.html(this.tableTemplateWithEmptyTBodyTags());
  this.collection.each(this.renderRow);
  return this;
},

renderRow: function () {
  var row = new App.Views.StockRow({
    model:      stock,
    suppliers:  this.suppliers
  });
  this.$el.find('tbody').append(row.render().el);
  return this;      
}

然后在表格视图之外,您可以执行suppliers.fetch()。当响应返回时应该触发重置。