我是第一次构建主干应用程序 - 进展顺利。
但是,我认为我没有以正确的方式为我的模型集合创建 View ,当我绑定(bind)事件时,它们会为每个 View 触发,而我只希望它们为一个 View 触发。
这是我的 Backbone 代码(片段):
(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:
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
}
]
}
];
这是我的 View 模板
<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>
View 正确组合,但当我单击一个 View 时,事件会在所有 View 上触发。有人可以指出我正确的方向吗?
最佳答案
由于您在 View 的 events
对象中省略了选择器,因此以下情况适用
根据主干 Documentation :
省略选择器会导致事件绑定(bind)到 View 的根元素 (this.el)。
问题是每个 SeriesGridItemView
将 click
事件绑定(bind)到 #model-grid
并且每个 View 都是 #模型网格
。在您的示例中,您注册了 5 个点击事件,当您点击任何 View 时,将触发所有 5 个事件。
在不更改任何其他代码的情况下,一种解决方案是将您的 events
对象设置为返回一个函数,这样您就可以为每个 View 指定一个 id
选择器。
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
指定为所有 View 的根元素。它最终看起来像: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);
});
一个侧面的建议
在您的
render
函数中,无需创建变量,您可以使用$
访问您的元素: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); },
关于javascript - 主干 DOM 事件多次触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18268616/