1

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

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

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

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

4

2 回答 2

5

你的问题就在这里:

_.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您尝试的功能不同.off。结果是每次创建视图的新实例时,都会将旧的滚动处理程序留在原处并添加一个新的处理程序。

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

remove: function() {
    $(window).off('scroll', this.handleScrolling);
    return Backbone.View.prototype.remove.apply(this);
}

然后view.remove()在创建新视图之前调用。

于 2013-06-20T03:21:28.287 回答
2

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

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

问题:演示

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

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

演示:小提琴

另一种解决方案是使用这样的共享处理程序

于 2013-06-20T02:49:08.780 回答