简体   繁体   English

Backbone:View事件触发多次

[英]Backbone: View Event triggers multiple times

I'm novice in Backbone. 我是Backbone的新手。 I want to show a stock list, where user can open up any stock right from the list and change stock values. 我想显示一个库存清单,用户可以从列表中打开任何库存并更改库存值。 After that the whole list should refresh to show changed values. 之后,整个列表应刷新以显示更改的值。

So as I found out it's better not only to create collection but create collection and a list of stock models. 因此,我发现不仅创建集合而且创建集合和库存模型列表更好。

For this I created a stock collection view for main table and stock model view for adding rows to the table where each row is a single model. 为此,我为主表和库存模型视图创建了一个库存集合视图,用于向表中添加行,其中每行是单个模型。

So this is a collection view: 所以这是一个集合视图:

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

And this is my stock row view: 这是我的股票行视图:

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

I wrote just a piece of code. 我只写了一段代码。 The problem is that when I click on '#open' that event triggers many times (right the quantity elements in the collection). 问题是,当我点击'#open'时,该事件会多次触发(正确的是集合中的数量元素)。 So when I catch e.currentTarget there are many similar objects. 因此,当我捕获e.currentTarget时,有许多类似的对象。 What i do wrong? 我做错了什么?

I suspect you have multiple things going on here. 我怀疑你这里有很多事情要发生。

Without seeing your template, I suspect each of your StockRow rows are rendering a tag with the id="open" . 在没有看到您的模板的情况下,我怀疑您的每个StockRow行都在呈现id="open"的标记。 Since id values should be unique, use a class in your link (example: class="open" ), and then reference that class in your click handler: 由于id值应该是唯一的,因此在链接中使用一个类(例如: class="open" ),然后在click处理程序中引用该类:

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

Next, since each instance of the StockRow already has a model instance associated with it, just use this.model instead of trying to look it up out of the data attribute of the currentTarget . 接下来,由于StockRow每个实例StockRow已经有一个与之关联的model实例,因此只需使用this.model而不是尝试从currentTargetdata属性中查找它。

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

But again, instead of using an id="stock" attribute in your template, use a class… say class="stock-preview" . 但同样,不要在模板中使用id="stock"属性,而是使用类...说class="stock-preview" Then just look for that in your open… 然后在你的公开场合寻找...

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

The other piece that looks questionable to me is the call to this.addAll(); 另一件对我来说有问题的是调用this.addAll(); in the render method of the StockTable view. StockTable视图的render方法中。 It is best practice to just have your render method render state, instead of having it trigger an ajax call to fetch the state. 最好的做法是让渲染方法呈现状态,而不是让它触发ajax调用来获取状态。

For example, in your initialize you can setup some event handlers that react to your collection changing state (below is an incomplete example, just hoping to get you going in the right direction): 例如,在初始化中,您可以设置一些对您的集合更改状态做出反应的事件处理程序(下面是一个不完整的示例,只是希望让您朝着正确的方向前进):

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

And then outside the table view, you can do a suppliers.fetch() . 然后在表视图之外,您可以执行suppliers.fetch() Which when the response comes back should trigger the reset. 当响应返回时应该触发重置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM