我正在创建一个Backbone.js应用程序,它包含一个索引视图和几个基于id的子视图。所有视图都与mousedown和mouseup事件绑定在一起。但是每当我从子视图转到索引视图然后再次转到任何子视图时,当前子视图中的mousedown和mouseup事件将再次被触发,这意味着当我单击子视图时,会有几个连续的触发了mousedown事件,随后触发了几个连续的mouseup事件。
查看完代码后,我终于发现导致此问题的是路由器。我的部分代码如下:
routes: {
"": "index",
"category/:id": "hashcategory"
},
initialize: function(options){
this._categories = new CategoriesCollection();
this._index = new CategoriesView({collection: this._categories});
},
index: function(){
this._categories.fetch();
},
hashcategory: function(id){
this._todos = new TodosCollection();
this._subtodolist = new TodosView({ collection: this._todos,
id: id
});
this._todos.fetch();
}
如您所见,我在路由器的initialize
方法中创建了索引集合和视图,但是我在路由器的相应路由功能中创建了子视图集合和视图。我尝试将索引集合和视图放在index
函数中,索引视图中的click事件的行为方式与子视图相同。所以我认为这就是为什么mousedown和mouseup会被触发几次。
但问题是,我必须使用id
作为发送到子视图的参数之一。所以我无法在initialize
方法中创建子视图。更重要的是,我已经看到其他人基于Backbone的项目,其中一些也在相应的路由功能中创建子集合和视图,但他们的应用程序运行完美。所以我不知道问题的根源是什么。有人能给我一些想法吗?
答案 0 :(得分:1)
听起来你有代表问题,因为:
所有子视图都使用相同的
<div>
元素
骨干视图使用jQuery el
<div>
绑定到事件。如果您的视图使用el
作为其<div>
,然后您通过替换包含的HTML将相同的<div>
用于其他视图,那么您最终会将两个视图附加到delegate
通过两个不同的delegate
来电。如果再次交换视图,您将有三个视图通过三个<div id="view-goes-here"></div>
接收事件。
例如,假设我们有这个HTML:
var V0 = Backbone.View.extend({
events: { 'click button': 'do_things' },
render: function() { this.$el.html('<button>V0 Button</button>'); return this },
do_things: function() { console.log('V0 clicked') }
});
var V1 = Backbone.View.extend({
events: { 'click button': 'do_things' },
render: function() { this.$el.html('<button>V1 Button</button>'); return this },
do_things: function() { console.log(V1 clicked') }
});
和这些观点:
which
我们用这样的东西在它们之间切换(当然which = (which + 1) % 2;
var v = which == 0
? new V0({el: $('#view-goes-here') })
: new V1({el: $('#view-goes-here') });
v.render();
从0开始):
which = (which + 1) % 2;
if(current)
current.undelegateEvents(); // This detaches the `delegate` on #view-goes-here
current = which == 0
? new V0({el: $('#view-goes-here') })
: new V1({el: $('#view-goes-here') });
current.render();
然后你将遇到我上面描述的多代理问题,这种行为似乎与你所描述的症状相符。
以下是一个易于查看的演示:delegate
解决此问题的一种快捷方法是在呈现新视图之前在当前视图上调用http://jsfiddle.net/ambiguous/AtvWJ/:
el
更好的方法是为每个视图提供自己独特的delegate
,这样当您替换HTML时,所有内容(包括<div><div>real stuff</div></div>
绑定)都会消失。你最终可能会遇到很多{{1}}结构,但这不值得担心。