Backbonejs事件多次发生

时间:2011-03-28 03:33:52

标签: backbone.js

我有一个在网格中显示项目的视图。如果单击用于创建新行的按钮,则会显示一个弹出窗口(使用SimpleModal)以允许用户将该行保存到服务器。如果一切顺利,窗口关闭,网格刷新。到目前为止,一切正常。如果我现在再次打开窗口,保存记录事件将被调用两次。如果我第三次关闭并打开窗口,那么事件将被调用三次,等等。我不知道为什么事件会多次反弹。以下是我的两个观点:

FieldList查看:

var fieldListView = Backbone.View.extend({
el: "#centerbodycontent",
initialize: function () {
    _.bindAll(this, 'render', 'addField');
},

render: function () {
    $(this.el).empty();
    $("#FieldGridTemplate").tmpl({ results: this.model }).appendTo(this.el)
    stripe($(this.el).find("tbody"));
    return this;
},
events: {
    "click a#addfield": "addField"
},
addField: function (e) {
    window.appController.popup = new fieldFormView({ model: new fieldModel({ contenttype_id: this.model.id }) });
    window.appController.popup.render();
}

});

表格视图(这是弹出窗口的名称)

var fieldFormView = Backbone.View.extend({
el: "#popupwindowcontent",

events: {
    "click #savefieldandnew": "savefield",
    "click #savefieldandclose": "savefield",
    "change input,textarea,select": "changeField"
},
render: function () {
    var formWrapper = $(this.el).find(".modal-form")[0];
    $(formWrapper).empty();
    $("#FieldFormTemplate").tmpl({ results: this.model }).appendTo(formWrapper)
    OpenForm(this.el, "Add Field", 450, 600);
    return this;
},
// automatically updates the model during field changes
changeField: function (e) {
    var changeobj = new Object;
    switch (e.target.type) {
        case "radio":
            changeobj[e.target.id] = parseInt($(e.target).val());
            break;
        case "checkbox":
            changeobj[e.target.id] = $(e.target).is(":checked");
            break;
        default:
            changeobj[e.target.id] = $(e.target).val();
            break;
    }

    if (e.target.id.toLowerCase() == "name") {
        var k = $(this.el).find("#key");
        if (jQuery.trim(k.val()).length == 0)
            k.val($(e.target).val().replace(/[^a-zA-Z0-9]+/g, '').toLowerCase());

        var l = $(this.el).find("#label");
        if (jQuery.trim(l.val()).length == 0)
            l.val($(e.target).val());
    }

    var options = { silent: true };
    this.model.set(changeobj, options);
},
savefield: function (e) {
    var kcode = (e.which);
    var thiz = this;
    var m = this.model;
    var nextaction = e.target.id;
    alert(nextaction);
    if (kcode == 0 || kcode == 1 || kcode == 32) {
        e.preventDefault();
        if ($("#contentfieldform").validate({
            rules: {
                name: { required: true },
                label: { required: true },
                key: { required: true }
            }
        }).form()) {
            m.save(null, {
                headers: { "If-Match": m.get("version") },
                error: function (model, response) {
                    var errResp = JSON.parse(response.responseText);
                    popupException("Content Type Modification Error", errResp.errors[0].message);
                },
                success: function (model, response) {
                    window.appController.popup.model = new fieldModel;
                    $.pnotify({
                        pnotify_title: 'Field Saved',
                        pnotify_text: 'The field was saved successfully.'
                    });

                    if (nextaction == "savefieldandclose") {
                        $.modal.close();
                    }
                }
            });
        }
    }
}

3 个答案:

答案 0 :(得分:23)

由于没有人回答我以为我会添加更多信息以防任何人遇到此问题。解释正在发生的事情(并提供通用解决方案)的良好资源是http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/。此外,最新版本的骨干网有一些新方法可以从视图中取消注册事件。

答案 1 :(得分:5)

今天早上我也有同样的头痛,但发现小的解决方法对我来说就像是一种魅力。

主要思想是每次我们需要显示某些内容时避免创建新的View对象,而是尝试重用旧的view对象。就我而言,它看起来像这样:

   Overview: backBone.View.extend({
        el: $('#overviewTab'),

        dialog : null,

对话框是我要保存视图对象的字段

现在在创建新视图的回调中我这样做:

showNewActivityDialog: function () {
            this.dialog = this.dialog || new window.RTB.Views.NewActivity();
            this.dialog.render();
            return false;
        },

在这种情况下我不创建新视图 - 我重用以前创建的,所以我不绑定新事件!
希望它对你有用

答案 2 :(得分:0)

快速修复(我不鼓励)是使用_.throttle函数。使用它来包装你的事件处理程序,使它只被调用一次,比如说100毫秒。它可能适用于UI,而不适用于app逻辑。

addField: (function() {
    return _.throttle( function (e) {
        window.appController.popup = new fieldFormView({ model: new fieldModel({ contenttype_id: this.model.id }) });
        window.appController.popup.render();
    }, 100 );
})(),