2012-03-27 3 views
13

Wenn Sie mehrere Ansichtsmodelle auf einer Seite haben, wie stellen Sie sicher, dass Sie sie synchronisiert halten können? Wenn beispielsweise ein Element hinzugefügt oder eine Schaltfläche auf ein Ansichtsmodell geklickt wird und Sie möchten, dass das andere Ansichtsmodell auf diese Änderung reagiert, kann Knockout dies nativ verwalten oder ist es besser, eine Messaging- oder Pub/Sub-Architektur zu verwenden.Was ist der beste Weg zum Verknüpfen/Synchronisieren von Ansichtsmodellen in Knockout?

Ich möchte vermeiden, Observables zwischen Modellen zu verwalten.

Antwort

25

Knockout 2.0 enthält Funktionen, mit denen Sie grundlegende Pub/Sub tun können. Hier sehen Sie ein Beispiel, in dem zwei Ansichtsmodelle über einen Mediator kommunizieren.

var postbox = new ko.subscribable(); 

var ViewModelOne = function() { 
    this.items = ko.observableArray(["one", "two", "three"]); 
    this.selectedItem = ko.observable(); 
    this.selectedItem.subscribe(function(newValue) { 
     postbox.notifySubscribers(newValue, "selected"); 
    }); 
}; 

var ViewModelTwo = function() { 
    this.content = ko.observable(); 
    postbox.subscribe(function(newValue) { 
     this.content(newValue + " content"); 
    }, this, "selected"); 
}; 

ko.applyBindings(new ViewModelOne(), document.getElementById("choices")); 
ko.applyBindings(new ViewModelTwo(), document.getElementById("content")); 

Das erste View-Modell teilt durch die Postbox zu einem bestimmten Thema und das zweite Ansicht Modell abonniert dieses Thema. Sie haben keine direkte Abhängigkeit voneinander.

Natürlich müsste das Postfach nicht global sein und könnte in die View-Model-Konstruktorfunktionen übergeben oder nur in einer selbstausführenden Funktion erstellt werden.

Probe: http://jsfiddle.net/rniemeyer/z7KgM/

Auch könnte die postbox nur sein, ein ko.observable (die die ko.subscribable Funktionen enthält).

+0

das sieht gut aus, danke. – jaffa

+0

@RP Niemeyer - Was ist der Unterschied zwischen ko-beschreibbaren und beobachtbaren? – Ryan

+3

ko-beschreibbar ist eine Basis "Klasse", die beobachtbare und berechnete Observablen Funktionalität erhalten. Es stellt die grundlegenden Pub/Sub-Features zur Verfügung, die sowohl Observablen als auch berechnete Observablen verwenden. –

0

Sie scheinen zu widersprüchlichen Zielen zu fahren. Die Art und Weise, wie Sie das in Knockout tun würden, besteht darin, Observable zu erstellen, aber das scheinen Sie nicht zu wollen.

Wenn Sie Foo und Bar-Objekte mit Observablen haben, möchten Sie vielleicht keine Observablen auf Foo, die mit Bar oder umgekehrt interagieren, aber warum nicht ein Widget, das Foo und Bar überwacht und vermittelt?

+0

Was ist mit der Situation, wo Sie auf jeder Seite ein Suchfeld Modell haben?Sie möchten allen anderen Modellen mitteilen, dass sie den Text bei der Suche erneut binden müssen. Jede Seite hat das Suchfeldmodell, aber auf jeder Seite ein anderes Ansichtsmodell. – jaffa

0

Ich habe eine kleine Erweiterung erstellt, um dieses Problem für ein neues Projekt von mir zu lösen. Etwas ähnlich in der Methodik, aber fügt Subskriptionen direkt zu der veröffentlichten Observablen hinzu und wird Abonnenten in die Warteschlange stellen, wenn sie vor der Deklaration einer veröffentlichten Observablen deklariert werden.

Knockout PubSub

0

Die Art, wie ich zu synchronisieren Modelle gefunden wird, um die Postbox Bibliothek von RP Niemeyer

mit Jedoch habe ich etwas Interessantes über die observableArray gefunden. Und deshalb habe ich eine neue Antwort gefunden. Nur um die Antwort von Niemeyer zu vervollständigen.

Wenn Sie Postbox und ObservableArray verwenden, werden die Ereignisse "subscribeTo" und "publishOn" ausgelöst, wenn Sie ein Element aus observableArray hinzufügen oder entfernen. Wenn Sie ein Element innerhalb des Arrays aktualisieren, wird nichts ausgelöst. Ich denke, das hat nichts mit der Postbox-Bibliothek zu tun, sondern eine Knockout-Beschränkung.

Wenn Sie versuchen, das Ereignis beim Aktualisieren eines Elements eines beobachtbaren Arrays zu erhalten, ist es besser, die Methoden "publish" und "subscribe" aus der Postbox-Bibliothek zu verwenden.

Bitte beachten Sie die folgenden FIDDLE

-Code-Referenz:

function FundEntity (fund) 
{ 
    var self = this; 
    self.id = fund.id; 
    self.fundName = fund.fundName; 
    self.description = fund.description; 
    self.isFavorite = ko.observable(fund.isFavorite); 
} 


function GridViewModel(model) { 
    var self = this; 
    self.fundList = ko.observableArray(); 
    model.funds.forEach(function(fund) { 
     self.fundList.push(new FundEntity(fund)); 
    }); 
    self.favorite = function (id, index) { 
     var newValue = { 
      id: id, 
      index: index, 
      isFavorite: self.fundList()[index].isFavorite() 
     }; 
     ko.postbox.publish("itemChanged", newValue); 
     return true; 
    }; 
    self.isEditable = ko.observable().subscribeTo("myEditableTopic"); 
} 

function FundDetailViewModel(model) { 
    var self = this; 
    self.fundList = ko.observableArray(); 
    model.funds.forEach(function(fund) { 
     self.fundList.push(new FundEntity(fund)); 
    });  
    ko.postbox.subscribe("itemChanged", function (newValue) {   
     self.fundList()[newValue.index].isFavorite(newValue.isFavorite);   
    }); 
    self.editable = ko.observable(false).publishOn("myEditableTopic"); 
} 
Verwandte Themen