我有一个类别树,我想使用Backbone.js进行rending,而不是使用jQuery或在服务器端进行渲染。我有以下突破,我描述为模板:
<li>
<select class="categories">
<option value="">Select</option>
</select>
<input class="edit" type="button" value="Edit">
<input class="add" type="button" value="Add">
</li>
标记select
我作为内部视图单独渲染。当我更改选择时,我需要从服务器获取嵌套类别,并使用包含在标记li
中的上述模板将它们附加到标记ul
。在外部视图中,我创建内部视图并在编辑和添加时单击时监听事件。当嵌套级别超过一级时,我遇到了最后事件的问题,因为它们的触发次数与嵌套级别相同。我做错了什么?
以下代码段显示了我如何使用外部和内部视图:
var CategoriesInnerView = Backbone.View.extend({
tagName: 'select',
initialize: function(){
_.bindAll(this,'addOne','addAll');
this.collection.bind('reset',this.addAll);
},
addOne: function(category){
this.$el.append(new CategoryView({model:category}).render().el);
},
addAll: function(){
this.collection.each(this.addOne);
},
events: {
'change':'changeSelected'
},
changeSelected:function(){
var children = new Categories();
children.url = 'categories/' + this.$el.val();
var childrenView = new CategoriesOuterView({collection:children});
this.$el.parent().find('ul').remove();
this.$el.parent().append(childrenView.render().el);
children.fetch();
}
});
var CategoriesOuterView = Backbone.View.extend({
tagName: 'ul',
template: _.template($('#categories-template').html()),
initialize:function(){
this.inner = new CategoriesInnerView({collection:this.collection});
},
render: function(){
this.$el.html(this.template);
this.inner.setElement(this.$('select')).render();
return this;
},
events: {
'click .edit':'edit',
'click .add': 'add'
},
edit: function(){
this.renderForm(this.collection.get(this.inner.$el.val()));
},
add: function(){
this.renderForm(new Category());
},
renderForm:function(category){
// some code to render the form
}
});
答案 0 :(得分:3)
设置嵌套视图时,必须考虑事件将冒出DOM树并且Backbone在view.el级别处理DOM事件的事实。这意味着在您的方案中,如果让事件在层次结构中上升,嵌套节点也将触发父节点中的事件。
请参阅http://jsfiddle.net/PX2PL/了解演示
一个简单的解决方案是在回调中停止事件传播
var CategoriesOuterView = Backbone.View.extend({
events: {
'click .edit':'edit',
'click .add': 'add'
},
edit: function(e) {
e.stopPropagation();
this.renderForm(this.collection.get(this.inner.$el.val()));
},
add: function(e) {
e.stopPropagation();
this.renderForm(new Category());
}
}
答案 1 :(得分:2)
我们真的需要看一些你的代码才能正确回答这个问题,但这听起来像是发生了两件事之一:
1)您多次在同一元素上实例化视图
2)您的活动选择器过于宽泛
但是,如果没有真正看到(相关部分)您的观点,那么很难说更多。
与切向相关的旁注
顺便说一句,当你有这样的事情时,你可以采取两种基本方法:1)您可以让父视图创建子视图,并将事件处理放在子视图
上2)你可以让你的父视图创建或不创建子视图(它可以自己创建所有HTML),并将事件处理放在其上。
#1的优点是简单:您的事件处理程序可以引用this
来引用相关视图。但是,如果你需要扩展太多,那么#1会出现问题:数百万个视图,每个视图都有自己的事件处理程序,会影响性能。
所以,如果性能很重要,那么#2会更好,因为你只做了一组事件连接。但是,您的事件处理程序必须更加智能,因为他们必须根据提供的事件(即。e.target
,而不是this
来确定他们处理的元素。 1方法)。