2012-02-14 9 views
15

Ho una classe modello in KnockoutJS che ha più valori a cui vorrei iscrivermi. Ogni abbonamento svolgere lo stesso compito, in questo modo:KnockoutJS abbonarsi a più osservabili con la stessa azione di callback

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; }); 
} 

C'è un modo di combinare queste due chiamate per la sottoscrizione, in modo che possa utilizzare un solo abbonamento a 'guardare' entrambi i valori?

+0

Per chi cerca una soluzione più elaborato il plugin di seguito potrebbe essere opportuno prendere in considerazione: https://github.com/ZiadJ/knockoutjs-reactor – Ziad

risposta

23

È possibile utilizzare un osservabile calcolato per questo scopo. Devi solo assicurarti di accedere al valore di ciascun osservabile nella funzione di lettura. Sarebbe qualcosa di simile:

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

Quindi, si ottiene dipendenze i due osservabili e impostare la vostra bandiera.

Inoltre, se stai cercando qualcosa come una bandiera "sporca", potresti prendere in considerazione qualcosa come: http://www.knockmeout.net/2011/05/creating-smart-dirty-flag-in-knockoutjs.html. L'idea è che tu usi un osservabile calcolato che chiama ko.toJS() su un oggetto per scartare tutti i suoi osservabili.

+3

Ho visto questa soluzione e non sono contento perché il calcolo non sta davvero calcolando nulla, quindi il codice è più difficile capire. – wrschneider

+2

Gli oggetti osservabili calcolati non devono necessariamente restituire un valore. Il meccanismo di rilevamento delle dipendenze ha molti usi. Knockout usa i calcoli per tenere traccia delle dipendenze nei binding, ad esempio. Ecco un post recente su alcuni dei modi in cui i calcoli possono essere utilizzati: http://blog.safaribooksonline.com/2014/02/19/getting-knockout-js-computed-observables/ –

+1

@RPNiemeyer - sì, assolutamente funziona ed è conciso. Sto solo reagendo alla leggibilità. – wrschneider

14

Non si desidera duplicare il corpo della funzione del gestore? Estrailo in una variabile.

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

Nel passato, ho sempre preferito l'approccio calcolato. Ma quando vedo questo, mi sento come se in quei momenti potessi essere stato ubriaco con il succo a eliminazione diretta. Avendo ora costruito molte soluzioni aziendali utilizzando knockout, questo è il mio approccio preferito. – pimbrouwers

+1

Un lato positivo dell'uso dell'approccio calcolato è che è possibile utilizzare la limitazione della velocità sul calcolo per la limitazione – tarrball

1

Migliorare sul refactoring del corpo della funzione in una variabile, girando la lista delle dipendenze per tenere traccia in un loop:

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

È possibile creare una sorta di estensione per questo scopo. Semplice esempio:

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

Usage:

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') 
Problemi correlati