我有一个在网格中显示项目的视图。如果单击用于创建新行的按钮,则会显示一个弹出窗口(使用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();
}
}
});
}
}
}
答案 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 );
})(),