Backbone DOM事件多次触发 [英] Backbone DOM events firing multiple times
问题描述
大家好我是第一次建立一个骨干应用程序 - 它很棒!
Hi guys I'm building a backbone app for the first time - and its going great!
但是,我认为我没有为我创建视图以正确的方式收集模型,当我绑定事件时,我们只为每个视图触发它们。我只希望它们为一个视图开火。
However, I don't think I am creating views for my collection of models in the correct way and when I bind events they fire for every view when I only want them to fire for one.
这是我的骨干代码(一个片段) ):
Here is my backbone code (a snippet):
(function(){
Series = Backbone.Model.extend({
defaults:{
active:false
}
});
SeriesGridItemView = Backbone.View.extend({
el:'#model-grid',
defaults: {
active : false
},
initialize: function(){
this.render();
this.listenTo(this.model, 'change', this.setState);
},
render: function(){
this.template = _.template( $('#template-model-grid-item-view').html() );
this.view = $(this.template(this.model.toJSON())).appendTo(this.$el);
},
setState: function(){
this.active = this.model.get('active');
this.view.toggleClass('active',this.active);
},
events: {
'click':'toggle'
},
toggle: function(e){
e.stopPropagation();
e.preventDefault();
console.log('clicked');
return false;
}
});
SeriesCollection = Backbone.Collection.extend({
model: Series,
setPrice : function(p){
this.forEach(function(m){
var active = 0;
_.each(m.get('vehicles'),function(v){
if(v.price <=p){
v.active = true;
active++;
}
else{
v.active = false;
}
});
m.set('active',active>0);
});
}
});
series = new SeriesCollection(window.BMW.data.series);
series.forEach(function(m,i){
var c = i+1;
if(c > 3){
c%=3;
}
m.set('column','1');
new SeriesGridItemView({model:m});
});
})();
以下是构建模型的JSON:
And here is the JSON that constructs the models:
window.BMW.data.series = [
{
seriesId:1,
name:'1 Series',
slug:'1-series',
order:0,
vehicles:[
{
seriesId:1,
price:200
},
{
seriesId:2,
price:300
}
]
},
{
seriesId:2,
name:'3 Series',
slug:'3-series',
order:1,
vehicles:[
{
seriesId:1,
price:400
},
{
seriesId:2,
price:500
}
]
},
{
seriesId:3,
name:'4 Series',
slug:'4-series',
order:3,
vehicles:[
{
seriesId:1,
price:100
},
{
seriesId:2,
price:300
}
]
},
{
seriesId:4,
name:'6 Series',
slug:'6-series',
order:4,
vehicles:[
{
seriesId:1,
price:100
},
{
seriesId:2,
price:300
}
]
},
{
seriesId:6,
name:'X3',
slug:'x3',
order:5,
vehicles:[
{
seriesId:1,
price:500
},
{
seriesId:2,
price:800
}
]
}
];
这是我的观点模板
<script type="text/template" id="template-model-grid-item-view">
<div id="series-<%=seriesId%>" class="grid-item-view column-<%=column%>">
<div class="label"><%= name %></div>
<div class="thumbnail">
<img src="/Content/themes/BMW/img/series/small/<%= slug %>.png"/>
</div>
</div>
</script>
问题 - 视图正确汇编但当我点击一个视图时事件在所有视图上触发!有人可以指出我正确的方向吗?
The problem - the views assemble correctly but when I click one view the event fires on all of the views! Can someone please point me in the right direction?
谢谢,
杰克
推荐答案
由于您在视图的 events
对象中省略了选择器,因此适用
Since you omitted the selector in your events
object of your views the following applies
根据骨干文档:
省略选择器会导致事件绑定到视图的根元素(this.el)。
问题是每个 SeriesGridItemView
的bind 点击
事件到#model-grid
并且每个视图都是#model-grid
的子视图。在您的示例中,您注册了5个单击事件,当您单击任何视图时,将触发所有5个事件。
The problem is each of the SeriesGridItemView
's bind click
events to #model-grid
and each view is a child of #model-grid
. In your example, you register 5 click events and when you click on any of your views, all 5 events are triggered.
在不更改任何其他代码的情况下,一个解决方案是设置事件
对象以返回一个函数,这样你就可以了可以为每个视图指定 id
选择器。
Without changing any of your other code, one solution is to setup you events
object to return a function so you can specify an id
selector for each of your views.
events: function() {
var selector = '#series-' + this.model.get('seriesId'); // this id corresponds to your template id
var ev = {};
ev['click ' + selector] = 'toggle';
return ev;
},
另一个选项和我喜欢的选项是不指定#model-grid
作为所有视图的根元素。最终看起来像:演示
Another option and the one I prefer, is to not specify #model-grid
as your root element for all your views. It would end up looking like: demo
SeriesGridItemView = Backbone.View.extend({
// remove the following line
el:'#model-grid',
// .. all else is the same ../
});
series = new SeriesCollection(window.BMW.data.series);
series.forEach(function(m,i){
var c = i+1;
if(c > 3){
c%=3;
}
m.set('column','1');
$('#model-grid').append(new SeriesGridItemView({model:m}).el);
});
a side suggetion
A side suggetion
-
在
render
函数中,无需创建变量,可以使用$ $ c访问元素$ c>:
In your
render
function, there's no need to create variable, you can access your element by using$
:
render: function(){
this.template = _.template( $('#template-model-grid-item-view').html() );
this.$el.append(this.template(this.model.toJSON())));
},
setState: function(){
this.active = this.model.get('active');
this.$el.toggleClass('active',this.active);
},
这篇关于Backbone DOM事件多次触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!