使用handler的backbone.js scroll事件没有解除绑定

时间:2013-06-20 02:45:49

标签: backbone.js jquery

我将窗口的滚动事件绑定到视图的方法,如:

MyView = Backbone.View.extend({
  initialize: function(){
    _.bindAll(this, 'handleScrolling');
    $(window).off('scroll', this.handleScrolling).on('scroll', this.handleScrolling);
  }
})

我发现这不起作用。如果在实例化此视图时多次触发此回调。但是,如果我从off删除处理程序,那么它正确解除绑定并且每次滚动只触发一次。像:

$(window).off('scroll').on('scroll', this.handleScrolling);

知道为什么会这样吗?我不想从此事件中删除所有回调,因为其他视图/代码可能会将事件绑定到它,这会使应用程序出现意外情况。

有没有更好的方法将事件绑定到窗口/文档或当前视图范围之外的其他元素?

2 个答案:

答案 0 :(得分:4)

你的问题就在这里:

_.bindAll(this, 'handleScrolling');

这相当于:

this.handleScrolling = _.bind(this.handleScrolling, this);

因此,每次实例化视图时,您都会使用this.handleScrolling中的全新功能。然后你这样做:

$(window).off('scroll', this.handleScrolling)

但是,自this.handleScrolling附加的on函数以来,这将无法执行任何操作:

.on('scroll', this.handleScrolling);

与您尝试this.handleScrolling的{​​{1}}函数功能不同。结果是,每次创建视图的新实例时,都会保留旧的滚动处理程序并添加新的滚动处理程序。

正确的解决方案(IMO)是添加remove方法来正确清理:

.off

然后在创建新视图之前调用remove: function() { $(window).off('scroll', this.handleScrolling); return Backbone.View.prototype.remove.apply(this); }

答案 1 :(得分:2)

看起来你在每个调用中都有一个新的处理程序this.handleScrolling实例。

所以当jQuery尝试删除特定的处理程序时,它将无法在事件注册表中找到处理程序,因此它将无法删除它。

问题:Demo

我建议在这里使用事件命名空间

$(window).off('scroll.myview').on('scroll.myview', this.handleScrolling);

演示:Fiddle

另一种解决方案是使用像this

这样的共享处理程序