backbone.js - template - backbonejs github
El evento Backbonejs ocurre varias veces (3)
Como nadie respondió, pensé que agregaría más información en caso de que alguien se encuentre con esto. Un buen recurso para explicar lo que está sucediendo (y ofrecer una solución genérica) es http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/ . Además, la última versión de la red troncal tiene algunos métodos nuevos para permitir el registro de eventos desde las vistas.
Tengo una vista que muestra elementos en una grilla. Si se hace clic en un botón para crear una nueva fila, se muestra una ventana emergente (use SimpleModal) para permitir que el usuario guarde la fila en el servidor. Si todo va bien, la ventana se cierra y la cuadrícula se actualiza. Todo funciona bien hasta este punto. Si ahora abro la ventana por segunda vez, el evento de guardar registro se llamará dos veces. Si cierro y abro la ventana una tercera vez, entonces el evento se llamará tres veces, etc. No tengo idea de por qué el evento se está recuperando varias veces. Aquí están mis dos puntos de vista:
Vista 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();
}
});
Vista de formulario (esto es lo que se llama para la ventana emergente)
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();
}
}
});
}
}
}
Tengo el mismo dolor de cabeza esta mañana, pero encontré una pequeña solución que funciona como un encanto para mí.
La idea principal es evitar la creación de nuevos objetos de visualización cada vez que necesitamos mostrar algo, en su lugar, trato de reutilizar el objeto de vista anterior. En mi caso, se ve así:
Overview: backBone.View.extend({
el: $(''#overviewTab''),
dialog : null,
diálogo es mi campo donde voy a mantener mi objeto de vista
ahora en la devolución de llamada que crea una nueva vista hago esto:
showNewActivityDialog: function () {
this.dialog = this.dialog || new window.RTB.Views.NewActivity();
this.dialog.render();
return false;
},
en este caso, no creo nuevas vistas. Reutilizo una creada previamente, ¡así que no enlazo nuevos eventos!
Espero que funcione para ti
Una solución rápida (que no recomiendo) es usar la función _.throttle. Úselo para envolver su controlador de eventos para que solo se llame una vez cada, digamos 100 ms. Puede funcionar para la interfaz de usuario, no para la lógica de la aplicación.
addField: (function() {
return _.throttle( function (e) {
window.appController.popup = new fieldFormView({ model: new fieldModel({ contenttype_id: this.model.id }) });
window.appController.popup.render();
}, 100 );
})(),