0

我正在制作一个 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函数中,索引视图中的单击事件的行为方式与子视图相同。所以我认为这就是为什么 mousedown 和 mouseup 会被触发多次。

但问题是,我必须使用id作为发送到子视图的参数之一。所以我不能在initialize方法中创建子视图。更重要的是,我已经看到别人的项目基于Backbone,其中一些还在相应的路由功能中创建子集合和视图,但他们的应用程序运行完美。所以我不知道我的问题的根源是什么。有人可以给我一些想法吗?

4

1 回答 1

1

听起来您遇到了委托问题,因为:

所有子视图都使用相同的<div>元素

主干视图使用 jQuerydelegate在其el. 如果您有一个使用 a<div>作为其的视图,el然后<div>通过替换包含的 HTML 将其用于另一个视图,那么您最终将<div>通过两个不同的delegate调用将两个视图附加到该视图上。如果再次交换视图,您将有三个视图通过三个delegates 接收事件。

例如,假设我们有这个 HTML:

<div id="view-goes-here"></div>

这些观点:

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当然从 0 开始):

which = (which + 1) % 2;
var v = which == 0
      ? new V0({el: $('#view-goes-here') })
      : new V1({el: $('#view-goes-here') });
v.render();

然后你会遇到我上面描述的多代表问题,这种行为似乎与你描述的症状相匹配。

这是一个易于查看的演示:http: //jsfiddle.net/ambiguous/AtvWJ/

解决此问题的一种快速简便的方法是undelegateEvents在渲染新视图之前调用当前视图:

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();

演示:http: //jsfiddle.net/ambiguous/HazzN/

更好的方法是让每个视图都有自己的独特性el,这样当您替换 HTML 时,所有内容(包括delegate绑定)都会消失。您最终可能会得到很多<div><div>real stuff</div></div>结构,但这不值得担心。

于 2012-05-03T03:28:18.910 回答