javascript - El evento de cambio del modelo no se activará al actualizar una matriz.
jquery backbone.js (5)
Usando backbone.js ...
@model.bind ''change'', ()-> console.log ''updated''
addIndex = (index) =>
array = @model.get(''array'')
array.push index
@model.set
array: array
Esto actualiza el modelo perfectamente pero no activa el evento de cambio. ¿Alguien sabe por qué mirando lo que publiqué?
EDITAR:
Agregué esto y desencadena el evento de cambio:
@model.set
test: ''''
num = 0
setInterval ()=>
num++
@model.set
test: num
, 3000
Agregué esto y no desencadena el evento de cambio:
@model.set
test: []
num = 0
setInterval ()=>
console.log ''testupdate''
num++
test = @model.get(''test'')
test.push num
@model.set
test: test
, 3000
¡La respuesta de Brian sobre el motivo es asombrosa!
Quería presentar otra forma de obtener lo que desea en lugar de anularlo o clonar la matriz.
Simplemente active manualmente el cambio:
addIndex = (index) =>
array = @model.get(''array'')
array.push index
@model.trigger(''change:array'',@model, array)
El problema es que está configurando el valor con el valor existente. Eche un vistazo al código fuente:
http://documentcloud.github.com/backbone/docs/backbone.html#section-33
Cuando llamas a set
, tiene una cláusula de guardia para asegurarte de que no estás configurando el mismo valor (para evitar bucles de eventos). En su caso, está obteniendo la matriz, modificándola y configurándola nuevamente, lo que no activará su evento.
Por supuesto, cuando set test: {}
, es un elemento nuevo con un nuevo objeto, por lo que se activará de nuevo. Si realmente desea desencadenar el evento, puede establecerlo en nulo, luego establecerlo en un conjunto vacío y luego en el conjunto poblado de nuevo ...
¿Podría considerar usar una colección Backbone en lugar de una matriz, y luego vincularla para cambiar los eventos en esa colección?
Como está configurando el objeto al que se hace referencia, use _.clone()
.
test = _.clone @model.get(''test'')
test.push num
@model.set test: test
Como ya no está utilizando el objeto / matriz referenciado para establecerse a sí mismo, activará el evento de cambio si ha cambiado.
Otra forma de hacerlo, al cambiar objetos o matrices, es desarmar silenciosamente la propiedad antes de establecer el nuevo valor actualizado. Algo como esto:
(function() {
var arr, model = new Model();
model.set( "arrayProp", [1, 2, 3] );
arr = model.get( "arrayProp" );
arr.push( 4 );
model.unset( "arrayProp", { silent: true } );
model.set( "arrayProp", arr );
})();
Al configurar silent: true
al desactivar el accesorio, el evento de cambio solo se disparará una vez (cuando se llama al método set()
y la propiedad se ha actualizado).
No hay realmente una diferencia entre hacer esto o llamar manualmente al evento, es solo una cuestión de preferencia personal.