2012-02-14 11 views
15

Tengo una clase de modelo en KnockoutJS que tiene múltiples valores a los que me gustaría suscribirme. Cada suscripción se realice la misma tarea, así:KnockoutJS suscribirse a múltiples observables con la misma acción de devolución de llamada

function CaseAssignmentZipCode(zipCode, userId, isNew) { 
    var self = this; 
    self.zipCode = ko.observable(zipCode); 
    self.userId = ko.observable(userId); 
    self.isNew = isNew; 
    self.isUpdated = false; 

    self.zipCode.subscribe(function() { self.isUpdated = true; }); 
    self.userId.subscribe(function() { self.isUpdated = true; }); 
} 

¿Hay una manera de combinar estas dos llamadas para la suscripción, de modo que pueda utilizar una suscripción a 'reloj' ambos valores?

+0

Para aquellos que buscan una solución más elaborada por debajo del plug-in valdría la pena considerar: https://github.com/ZiadJ/knockoutjs-reactor – Ziad

Respuesta

23

Puede utilizar un observable calculado para este fin. Solo necesita asegurarse de tener acceso al valor de cada observable en la función de lectura. Sería algo así como:

ko.computed(function() { 
    self.zipCode(); 
    self.userId(); 
    self.isUpdated = true; 
}); 

Así, se obtiene dependencias de los dos observables y establecer su bandera.

Además, si está buscando algo así como una bandera "sucia", entonces podría considerar algo como: http://www.knockmeout.net/2011/05/creating-smart-dirty-flag-in-knockoutjs.html. La idea es usar un observable calculado que llame a ko.toJS() en un objeto para desenvolver todos sus observables.

+3

He visto esta solución y no estoy contento con ella porque la computación no está realmente computando nada, por lo que el código es más difícil comprender. – wrschneider

+2

Los observables calculados no necesariamente tienen que devolver un valor. El mecanismo de seguimiento de dependencia tiene muchos usos. Knockout utiliza computeds para rastrear dependencias en enlaces, como un ejemplo. Aquí hay una publicación reciente sobre algunas de las formas en que se pueden usar computeds: http://blog.safaribooksonline.com/2014/02/19/getting-knockout-js-computed-observables/ –

+1

@RPNiemeyer - sí, es absolutamente funciona y es conciso. Solo estoy reaccionando a la legibilidad. – wrschneider

14

¿No desea duplicar el cuerpo de la función del manejador? Extraerlo a una variable.

function CaseAssignmentZipCode(zipCode, userId, isNew) { 
    var self = this; 
    self.zipCode = ko.observable(zipCode); 
    self.userId = ko.observable(userId); 
    self.isNew = isNew; 
    self.isUpdated = false; 

    var handler = function() { self.isUpdated = true; }; 

    self.zipCode.subscribe(handler); 
    self.userId.subscribe(handler); 
} 
+0

En el pasado, siempre he favorecido el enfoque calculado. Pero cuando veo esto, siento que en esos momentos podría haber estado ebrio con el jugo de knockout. Habiendo construido muchas soluciones empresariales utilizando knockout, este es mi enfoque preferido. – pimbrouwers

+1

Una ventaja para usar el enfoque calculado es que puede usar la limitación de velocidad en el cálculo de estrangulación – tarrball

1

Mejorando la refactorización del cuerpo de la función en una variable, girando la lista de dependencias para realizar un seguimiento en un bucle:

function CaseAssignmentZipCode(zipCode, userId, isNew) { 
    var self = this; 
    self.zipCode = ko.observable(zipCode); 
    self.userId = ko.observable(userId); 
    self.isNew = isNew; 
    self.isUpdated = false; 

    var handler = function() { self.isUpdated = true; }; 

    ko.utils.arrayForEach([self.zipCode, self.userId], function(obs) { 
    obs.subscribe(handler); 
    }); 
} 
2

Usted puede crear una especie de una extensión para este propósito. Un simple ejemplo:

function subscribeMany(callback, observables) {  
    for (var i = 0; i < observables.length; i++) { 
     observables[i].subscribe(callback); 
    } 
} 

Uso:

var name = ko.observable(); 
var email = ko.observable(); 

var callback = function(value) { 
    console.log(value); 
}; 

subscribeMany(callback, [name, email]); 

name('test 1') 
email('test 2') 
Cuestiones relacionadas