我该如何在打开一个SimpleModal对话框的BackBone.js视图中取消绑定事件?

How should I unbind events in BackBone.js view that opens a SimpleModal dialog?

本文关键字:js BackBone 对话框 视图 事件 绑定 取消 SimpleModal 一个      更新时间:2023-09-26

每次我创建一个视图并打开对话框时,我都会得到n组事件,其中n是对话框打开的次数。在下面的示例中,每次单击fooButton时,我将获得n按钮单击事件。我知道我应该解除绑定事件,但this.undelegateEvents()不工作。

根据我对SimpleDialog(和其他对话框小部件的工作方式)的理解,当创建对话框时,div的内容被复制到另一个元素中,这表明我应该能够捕获创建的元素(例如$dialog = this.$el.modal();),然后调用unelegateevents。这个方法也行不通。

任何想法?

MyDialogView = Backbone.View.extend({
    initialize: function(options){
        this.render();
    },
    render: function() {
        this.$el.empty().append("<button id='fooButton'>Foo</button>");
        this.$el.modal({ "static": true });
    },
    events: {
        "click #fooButton": "fooPressed"
    },
    fooPressed: function() {
        alert("clicked");
        $.modal.close();
    }
});
$(function(){
    $("#openDialog").click(function() {
        new MyDialogView({el: $("#dialog") });
    });
});

谢谢你的帮助!

通过切换到JQuery UI Dialog解决。

每次实例化视图时,Backbone将在el上调用delegateEvents:

delegateEvents delegateEvents([events])

[…默认情况下,delegateEvents在View的构造函数中为你调用,[…]

所以每次你这样做的时候:

new MyDialogView({el: $("#dialog") });

你正在附加一个jQuery delegate#dialog。你的问题是你没有自己清理,你应该在关闭对话框时删除delegate

你应该在关闭对话框时调用undelegateEvents:

fooPressed: function() {
    alert("clicked");
    this.undelegateEvents();
    $.modal.close();
}

或者,您可以创建一次视图,然后调用一些方法根据需要弹出它。在您的设置中,您将从initialize中删除render调用,所有new MyDialogView(...)仅一次并将视图保存在变量中,然后根据需要保存my_dialog_view.render()

您使用的是什么版本的Backbone ?从0.9.9开始:

最重要的是,主干事件有两个新方法:listenTo和stoppllistening。这是一种常用的on和off的反转控制风格,可以更容易地清理一个对象在其他对象上侦听的所有事件。当你用view.remove()销毁视图时,这将自动完成。请注意,在垃圾收集语言中编程的通常规则仍然适用。

我猜每次你打开你的模式,你的关闭按钮应该调用view.remove()。在最新版本中,Backbone现在应该从视图中解除所有事件的绑定,而不必手动执行。

MyDialogView = Backbone.View.extend({
    initialize: function(options){
        this.render();
    },
    render: function() {
        this.$el.empty().append("<button id='fooButton'>Foo</button>");
        this.$el.modal({ "static": true });
    },
    events: {
        "click #fooButton": "fooPressed",
        "click #close": "closeView"
    },
    closeView: {
      this.remove();
      $.modal.close();
    },
    fooPressed: function() {
        alert("clicked");
    }
});

如何使用jQuery的off方法?

unbindEvents : function(){
    this.$el.off();
}

如果每次单击'#openDialog'时不创建MyDialogView的新实例,而只是渲染现有的实例,该怎么办?

MyDialogView = Backbone.View.extend({
    initialize: function(options){
        //this.render(); // don't need to call it here
    }
    // ...
});
$(function(){
    var myDialogView = new MyDialogView({
        el: $("#dialog")[0]
    });
    $("#openDialog").click(function() {
        myDialogView.render();
    });
});

我的同事Anton找到了一个解决方案,用JQuery UI Dialog替换Simple Modal,因为它返回一个可以安全地分配给this的元素。$el(简单模式不能)。在开放:

that.$el = $(that.$el.dialog({
    modal: true,
    resizable: false,
    "beforeClose": function (dialog) {
        that.stopListening();
        that.undelegateEvents();
    }
}));

再次感谢每一个试图帮助的人,希望这对将来的人有帮助。

在错误的作用域中使用this,所以在这种情况下,this被引用到一个方法而不是视图实例。这是我以前做过的删除事件视图的方法,它工作得很好。

var JobContainerNumberView = Backbone.View.extend({
events: {
        "focusout input.txtNumber": "checkBookingExists"
    },
    checkBookingExists: function() {
        var _this = this;
        var this_input = _this.$('input.txtNumber'); // text box where container is
        var booking_number = this_input.val();
        if ( booking_number != '') {
            $.post('booking/booking_exists', {'booking_number': booking_number},
                function(data,status,xhr) {
                if (data.exists) {
                    alert(data.message);
                    // stop only focusout event for the input
                    $(_this.el).off('focusout', 'input.txtNumber');
                    //remove all events on view
                    //_this.undelegateEvents();
                }
            },'json');
        }
    }

});