我有一个看起来像的视图:
var ListItemButtonView = Backbone.Marionette.ItemView.extend({
tagName: 'button',
className: 'listItem-button',
events: {
'click': '_onClick',
'dblclick': '_onClick'
},
// Debounced to defend against accidental/spam clicking.
_onClick: _.debounce(function () {
if (!this.$el.hasClass('disabled')) {
this._doOnClick();
}
// Don't allow click to bubble up to the list item and cause a selection.
return false;
}, 100, true),
_doOnClick: function(){
this.model.destroy();
console.log('Do on click has ran');
}
});
这段代码在本地对我来说很好用,并且我没有遇到任何问题。在生产中,我看到一个错误,指示
_doOnClick
正在运行多次。这对我来说没有意义,因为在模型被销毁时,视图已被删除。第二个model.destroy命令应该是不可能的。另外,我通过将立即设置为true的功能反跳来保护_onClick事件。在下划线的文档http://underscorejs.org/#debounce中,它表示:“为即时参数传递true导致触发反跳
该功能位于等待的前沿而不是后沿
间隔。在防止意外情况下有用
双击第二次触发的“提交”按钮。”
我的实现是否存在任何不正确之处,可能导致某些用户设法多次运行_doOnClick?
编辑:
到目前为止,我唯一的预感是,如果用户的计算机运行特别慢,则100ms的延迟可能不足以清理视图。我增加了延迟,然后看看能否解决任何问题。
最佳答案
将延迟增加到1s使问题消失了。不过,可能还有一个更优雅的解决方案。
这是我的代码现在的样子。请注意,我对结构进行了一些更改,因为将函数定义为在类声明级别而不是在实例化时进行了反跳操作,这导致计时器在视图的所有实例之间共享,而不是为每个实例提供单独的计时器。
var ListItemButtonView = Marionette.ItemView.extend({
tagName: 'button',
className: 'listItem-button',
events: {
'click': '_onClick',
'dblclick': '_onDblClick'
},
initialize: function () {
// Debounced to defend against accidental/spam clicking. Bound in initialize because
// the debounce timer will be shared between all ListItemButtonViews if bound before initialize.
this._debounceOnClickAction = _.debounce(this._doOnClickAction.bind(this), 1000, true);
},
_onClick: function () {
this._debounceOnClickAction();
// Don't allow click to bubble up since handling click at this level.
return false;
},
_onDblClick: function () {
this._debounceOnClickAction();
// Don't allow dblClick to bubble up since handling click at this level.
return false;
},
_debounceOnClickAction: null,
_doOnClickAction: function() {
if (!this.$el.hasClass('disabled')) {
this.doOnClickAction();
}
}
});