我有一个看起来像的视图:

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

10-07 18:03