2012-03-27 11 views
14

Dado el siguiente fragmento:¿Por qué mi modelo Backbone hasChanged() siempre devuelve false?

var m = new Backbone.Model({ 
    name: 'joshua' 
}); 

m.set('name', 'something else'); 

Si ahora llamo m.hasChanged() o m.hasChanged('name') consigo false. ¿Por qué? Según tengo entendido, ambos deben devolver true.

m.changedAttributes() también devuelve falso.

Aquí es un violín que ilustra lo que estoy haciendo, y esperando: http://jsfiddle.net/9cvVv/88/

EDIT: Parece que a menos que pase { silent: true; } al método set() entonces se genera el evento change en su modelo que borra el changedAttributes(), etc. Básicamente, estas propiedades solo rastrean los cambios desde la última vez que se activó el evento change.

Lo leí en la documentación pero no lo entendí al principio.

Esto no me parece muy útil. Agradecería cualquier explicación de por qué esto funciona de la manera que lo hace y la mejor manera de lograr el resultado que quiero. (Que pasa alrededor de {silent: true; } y renunciar a la utilización del evento change parece un desperdicio.)

Respuesta

15

A menos que se pasa al método { silent: true; }set() entonces se genera el evento change en su modelo que limpia el changedAttributes(), etc. Se trata fundamentalmente propiedades solo realizan un seguimiento de los cambios desde la última vez que se activó el evento change.

Así que la respuesta es llamar a este lugar:

m.set('name', 'something else', {silent: true}) 
+0

Ajá. Hice un método 'save()' para las colecciones que envían un lote de modelos y devoluciones. Me preguntaba por qué hasChanged() no pareció hacer nada. :-) ¡Gracias! – jmk2142

+0

Esto ya no es cierto en las versiones más nuevas de Backbone; ver mi respuesta – pimlottc

+0

Guardado mi día con backbone 0.9.2 ... – gor181

-7

Model.set() toma un hash de atributos como el primer argumento. Pruebe m.set({'name': 'something else'});. Hacer m.set('name', 'something') no establece 'nombre', por lo que nunca desencadena el evento change y su llamada al hasChanged() devuelve false. Siempre puede inspeccionar el valor actual del hash de atributos cerrando la sesión m.attributes, aunque no se recomienda acceder y manipularlo directamente ya que ninguno de los eventos de cambio se activará de esa manera.

+1

Incorrecto. 'Model.set()' admite tanto un hash como un único atributo como I'm using. El atributo se está configurando, como se puede ver en [este violín ligeramente expandido] (http://jsfiddle.net/H2raK/1/). Esto también se ilustra [en la documentación de Backbone.js] (http://backbonejs.org/#Model-set). – joshuapoehls

+0

Lo siento, debería haber leído más cerca. ¿Qué es exactamente lo que estás tratando de hacer? Simplemente podría vincularse al evento 'change' del modelo. De esta forma puede verificar los atributos específicos para el cambio w/'hasChanged (attr)' (para ver si necesita actualizar cierta parte de la vista). Edité tu [violín] (http://jsfiddle.net/H2raK/4/) para ilustrar esto. – meirish

+0

Básicamente, estoy tratando de obtener la lista de propiedades que han cambiado desde que se guardó el modelo. Por ahora estoy pasando '{silent: true}' alrededor y luego revisando el 'changedAttributes()'. Esto funciona exactamente como lo necesito, solo esperaba que Backbone funcionara más como la bandera tradicional 'isDirty' en un modelo de datos. – joshuapoehls

11

Esta publicación se basa en el comportamiento anterior de las versiones anteriores de Backbone. hasChangedhace ahora (as of 0.9.10) siempre devuelve true después de que se llama set(..). La bandera silent ya no tiene ningún efecto.

Esto está confusamente enmascarado en el jsfiddle vinculado en la pregunta que utiliza una copia alojada en CDN de backbone.js que siempre usa la última versión. He aquí algunos jsfiddles actualizados que muestran el cambio en el comportamiento:

Cuestiones relacionadas