我有一个看起来像的视图:
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以使debounce触发 前导上的函数而不是等待的后沿 间隔。在防止意外情况下很有用 双击"提交"按钮从第二次开火。"
我的实施有什么不正确可能导致一些用户设法多次运行_doOnClick吗?
编辑:
到目前为止,我唯一的预感是,如果用户的机器运行速度特别慢,那么100ms的延迟时间可能不足以清理视图。我已经增加了延迟,看看是否可以解决任何问题。
答案 0 :(得分:1)
将延迟增加到1秒会使问题消失。不过,那里可能有更优雅的解决方案。
这是我的代码现在的样子。请注意,我稍微更改了结构,因为在类声明级别将函数定义为debounced而不是在实例化时导致计时器在视图的所有实例之间共享,而不是为每个实例提供单独的计时器。
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();
}
}
});