3

每次创建视图并打开对话框时,我都会收到n一组事件,其中n对话框打开的次数是多少。在下面的示例中,每次单击fooButton我都会收到n按钮单击事件。我知道我应该取消绑定事件但this.undelegateEvents()没有工作。

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

有任何想法吗?

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 解决。请看下面我的回答。

4

6 回答 6

3

每次实例化视图时,Backbone 都会delegateEvents调用el

委托事件 delegateEvents([events])

[...] 默认情况下,delegateEvents在视图的构造函数中为您调用,[...]

所以每次你这样做:

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

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

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

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

或者,您可以创建一次视图,然后根据需要调用一些方法将其弹出。通过您的设置,您只需一次从中删除render呼叫并将视图保存在变量中,然后根据需要进行。initializenew MyDialogView(...)my_dialog_view.render()

于 2012-12-23T23:34:25.233 回答
1

您使用的是哪个版本的 Backbone?从 0.9.9 开始:

最重要的是,Backbone 事件有两个新方法:listenTo 和 stopListening。这些是通常的 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");
    }
});
于 2012-12-24T15:57:09.250 回答
0

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

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

再次感谢所有试图提供帮助的人,希望这对未来的人有所帮助。

于 2012-12-24T04:15:36.357 回答
0

使用jQuery的off方法怎么样?

unbindEvents : function(){
    this.$el.off();
}
于 2012-12-23T22:30:22.617 回答
0

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

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();
    });
});
于 2012-12-23T22:32:03.927 回答
0

在错误的范围内使用该问题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');
        }
    }

});

于 2014-11-20T07:38:30.150 回答