var RowView = Backbone.View.extend({
tagName: 'li',
className: 'course-row',
events: {
"click .table-row": "rowClick" // problem here!
},
initialize: function() {},
template: _.template(tpl),
render: function() {
var rowStr = this.template({course: this.model});
$(this.el).append(rowStr);
},
rowClick: function (e) {
alert(e);
}
});
上面的代码定义了Backbone Row视图。我想在表格中创建和渲染几行,所以我做了:
data.forEach(function(rowData){
var row = new RowView({model: course, el: mountPoint});
row.render();
});
如果我创建了2行,则事件绑定两次(如果单击该行则为2 alert msg),3行3次。我通过在父视图中定义事件来避免此问题,但如果我真的需要在每一行附加事件处理程序,我该如何避免双事件绑定问题?
答案 0 :(得分:2)
你这样做:
data.forEach(function(rowData){
var row = new RowView({model: course, el: mountPoint});
row.render();
});
这意味着您的观点会忽略其tagName
和className
,然后继续将自己绑定到您提供的el
because:
this.el
可以从DOM选择器字符串或Element中解析出来;否则,它将从视图的tagName
,className
,id
和attributes
属性中创建。
一个视图的events
are bound to its el
using delegation,您正在绑定多个视图(恰好是相同的视图"类")所以当然您获得了多个视图事件绑定。
如果你的行真的应该是<li class="course-row">
元素,那么你想做几件事:
让RowView
创建并拥有自己的el
。将tagName
和className
属性保留在RowView
中,然后停止将el
传递给构造函数。您也应该将$(this.el)
更改为this.$el
,当Backbone已经为您隐藏了一个jQuery对象时,无需再创建另一个jQuery对象。
从this
&#39; RowView
返回render
,这是标准做法,让下一步更好一些。
无论创建RowView
的是什么,都应该创建它们,render
,然后将它们放在容器中。您似乎尝试使用mountPoint
(可能是<ul>
}作为容器,因此您想说:
data.forEach(function(rowData) {
var row = new RowView({model: course});
mountPoint.append(row.render().el);
// This is why (2) above -----^^^
});
假设mountPoint
是一个jQuery实例,如果情况并非如此,那么您想要代之以$(mountPoint).append(row.render().el)
(或者执行var $mountPoint = $(mountPoint)
以上forEach
并在其中使用$mountPoint.append
。
个人经验法则:如果您将el
传递给视图构造函数,那么您几乎肯定会犯错误。如果您确切知道为什么要将el
传递给构造函数,知道后果,并知道如何处理它们,那么您已经足够成年,可以用剪刀运行,所以请直接前进。