[英]Events in a Backbone view that can be added multiple times in the application
在解释我面临的问题之前,这是我正在使用的代码:
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.1/underscore-min.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js"></script>
<script type="text/template" id="view_template">
<li>
<label class="lbl" style="width:100px;display:inline-block;"><%= name %></label>
<button class="btn">Click</button>
</li>
</script>
<script type="text/javascript">
AppModel = Backbone.Model.extend({
defaults : {
m_name : "Default name"
},
modify : function(value) {
this.set({
m_name : value
});
}
});
$(document).ready(function() {
$("#add").click(function() {
var appModel = new AppModel();
appModel.modify($("#txt").val());
new CustomView({
model : appModel
});
$("#txt").val("");
});
CustomView = Backbone.View.extend({
el : $(".list"),
events : {
"click .btn" : "showAlert"
},
initialize : function() {
this.render();
},
render : function() {
var variables = {
name : this.model.get("m_name")
};
var t = _.template($("#view_template").html(), variables);
$(this.el).append(t);
},
showAlert : function() {
alert(this.model.get("m_name"));
}
});
});
</script>
</head>
<body>
<input type="text" id="txt"/>
<button id="add">
Add
</button>
<ul class="list" style="list-style: none"></ul>
</body>
</html>
这里有一个演示 - http://jsfiddle.net/jCekv/
您可以在文本字段中键入任意值,然后单击“添加”。文本将添加到作为骨干视图的列表中。您可以继续向列表中添加多个值。添加一些项目后,单击任何一个中的“单击”按钮。列表中的项目。我想获取该视图的模型中的值。但由于我添加Events
的方式,事件处理程序正在执行多次。例如:如果我添加3项并单击任何一项列表中的按钮3将出现一个警报 - 一个对应于添加的每个项目。这不是我想要的方式。我希望仅针对已单击的Backbone View触发事件,以便我可以访问我点击了Backbone View的模型。
我如何才能实现这一功能?。如果我的问题不明确,请告诉我。谢谢。
问题是所有的CustomViews
都将其元素设置为$(".list")
。 因此,所有委托事件都添加到相同的DOM元素,列表,而不是单个列表项。
请在此处查看可能的解决方案: http : //jsfiddle.net/mbuchetics/R8jPA/
我更改了CustomView
以使用li
的tagName
而不是设置元素。 模板不会附加到元素,而是设置其内容。 这样,每个CustomView
代表列表中的一个项目,而click事件恰好指的是该项目。 我还从初始化中删除了渲染调用,而是在将视图附加到列表时(在“添加单击”回调中)呈现视图。 Render()
返回this
,因此您可以使用view.render().el
来获取列表项的html。
您可以进一步改进应用程序以使用集合和集合的单独视图。 然后,集合视图可以处理集合上的“添加”等事件,并相应地更新自身(以及各个项目视图)。
这是因为您正在为每个项创建视图类的新实例,为每个实例分配相同的DOM元素(对应于整个列表,而不是单个项),并注册相同的事件侦听器。 因此,每次单击任何按钮时,事件侦听器都会为每个视图对象触发。
这样的东西会起作用:
$( document ).ready( function () {
$( "#add" ).click( function () {
var appModel = new AppModel();
appModel.modify( $( "#txt" ).val() );
var item = new Item_View( {
model : appModel
} );
list.add_item( item );
$( "#txt" ).val( "" );
} );
var List_View = Backbone.View.extend( {
el : $( ".list" ),
events : {
"click .btn" : "showAlert"
},
initialize : function () {
this.render();
},
add_item : function ( item ) {
item.render();
item.$el.data( 'view_object', item );
this.$el.append( item.el );
},
showAlert : function ( event ) {
alert(
$( event.target )
.closest( 'li' )
.data( 'view_object' )
.model.get( "m_name" )
);
}
} );
var Item_View = Backbone.View.extend( {
tagName : 'li',
render : function() {
var variables = {
name : this.model.get( "m_name" )
};
var t = _.template( $( "#view_template" ).html(), variables );
this.$el.html( $( t ).html() );
return this;
}
} );
var list = new List_View;
} );
我为列表和项目创建了单独的视图类。
我正在使用jQuery.data
存储对每个项目的视图对象的引用,以便可以在事件侦听器( showAlert
)中检索视图对象(以及通过它,模型对象)。 或者,您可以在列表视图中维护项目视图对象的数组。 我已经有了这个设置来通过列表视图的add_item
方法执行添加项目,这样便于维护这样的项目视图对象数组。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.