Knockout Observables

Wir haben gesehen, wie mit beobachtbaren Eigenschaften Knockout.js HTML-Elemente automatisch aktualisieren kann, wenn zugrunde liegende Daten geändert werden. Dies ist jedoch nur der Anfang ihres Dienstprogramms. Knockout.js bietet auch zwei weitere Möglichkeiten, ViewModel-Eigenschaften anzuzeigen: berechnete Observables und Observable Arrays. Gemeinsam eröffnen sie eine völlig neue Welt von Möglichkeiten für datengetriebene Benutzeroberflächen.

Berechnete Observables lassen Sie Eigenschaften erstellen, die dynamisch generiert werden. Das bedeutet, dass Sie mehrere normale Observables in einer einzigen Eigenschaft kombinieren können, und Knockout.js hält die Ansicht immer auf dem neuesten Stand, wenn sich darunterliegende Werte ändern.

Abbildung 12: Ein berechnetes Observable in Abhängigkeit von zwei normalen Observables

Beobachtbare Arrays Kombinieren Sie die Leistung der Observable von Knockout.js mit nativen JavaScript-Arrays. Wie native Arrays enthalten sie Listen von Elementen, die Sie bearbeiten können. Da sie jedoch beobachtbar sind, aktualisiert Knockout.js automatisch alle zugehörigen HTML-Elemente, wenn Elemente hinzugefügt oder entfernt werden.

Abbildung 13: Ein beobachtbares Array, das andere ViewModels enthält

Durch die Kombination von Observablen und die Möglichkeit, mit Listen von Elementen zu arbeiten, stehen Ihnen alle Datenstrukturen zur Verfügung, die Sie in einem ViewModel benötigen. In dieser Lektion werden beide Themen mit einer einfachen Warenkorbschnittstelle vorgestellt.


Berechnete Observables

Zuerst beginnen wir mit einem einfachen berechneten Beobachtbaren. Unter der Vorname und Nachname Observables in PersonViewModel, erstellen Sie den berechneten fullName-Observable:

 this.fullName = ko.computed (function () return this.firstName () + "" + this.lastName ();, this);

Dadurch wird eine anonyme Funktion definiert, die bei jeder Person den vollständigen Namen der Person zurückgibt PersonViewModel.fullName wird zugegriffen. Dynamische Generierung des vollständigen Namens aus den vorhandenen Komponenten (Vorname und lastName) verhindert, dass wir redundante Daten speichern, aber das ist nur die halbe Miete. Wir müssen diese Funktion an ko.computed () übergeben, um ein berechnetes Observable zu erstellen. Dies teilt Knockout.js mit, dass bei jeder Änderung von firstName oder lastName alle an die Eigenschaft fullName gebundenen HTML-Elemente aktualisiert werden müssen.

Stellen Sie sicher, dass unsere berechneten beobachtbaren Werke funktionieren, indem Sie die Zeile „John's Shopping Cart“ an binden vollständiger Name statt firstName:

 

Einkaufswagen

Jetzt sollte auf Ihrer Seite "John Smiths Einkaufswagen" angezeigt werden. Als Nächstes stellen Sie sicher, dass Knockout.js dieses HTML-Element synchronisiert, wenn Sie eine der zugrunde liegenden Eigenschaften ändern. Nach dem Binden einer Instanz von PersonViewModel, Versuchen Sie, die firstName-Eigenschaft zu ändern:

 var vm = new PersonViewModel (); ko.applyBindings (vm); vm.firstName ("Mary");

Dies sollte die Zeile in "Mary Smiths Einkaufswagen" ändern. Denken Sie auch daran, dass das Lesen oder Setzen von Observablen mit Funktionsaufrufen und nicht mit der Zuweisung erfolgen sollte (=) Operator.

Berechnete Observables bieten viele der gleichen Vorteile wie die automatische Synchronisierung der Ansicht von Knockout.js. Anstatt nachverfolgen zu müssen, welche Eigenschaften auf andere Teile von ViewModel angewiesen sind, können Sie mit Hilfe von berechneten Observables Ihre Anwendung um atomare Eigenschaften herum aufbauen und Abhängigkeiten nach Knockout.js delegieren.


Beobachtbare Arrays

Mit beobachtbaren Arrays können Knockout.js Listen von Elementen verfolgen. Wir werden dies erkunden, indem wir eine Warenkorb-Anzeigeseite für unseren Benutzer erstellen. Zunächst müssen wir ein benutzerdefiniertes Objekt zur Darstellung von Produkten erstellen. Ganz oben in unserem Skript, bevor Sie definieren PersonViewModel, Fügen Sie die folgende Objektdefinition hinzu:

 Funktion Produkt (Name, Preis) this.name = ko.observable (Name); this.price = ko.observable (price); 

Dies ist nur ein einfaches Datenobjekt zum Speichern einiger Eigenschaften. Beachten Sie, dass es möglich ist, mehreren Objekten beobachtbare Eigenschaften zu geben, und Knockout.js verwaltet alle Abhängigkeiten eigenständig. Mit anderen Worten, es ist möglich, Beziehungen zwischen ihnen herzustellen mehrere ViewModels in einer einzigen Anwendung.

Als Nächstes erstellen wir einige Instanzen unseres Neuen Produkt Klasse und fügen Sie sie dem virtuellen Einkaufswagen des Benutzers hinzu. Innen PersonViewModel, Definieren Sie eine neue beobachtbare Eigenschaft namens shoppingCart:

 this.shoppingCart = ko.observableArray ([neues Produkt ("Bier", 10.99), neues Produkt ("Brats", 7.99), neues Produkt ("Brötchen", 1.49)]);

Dies ist ein natives JavaScript-Array, das drei Produkte enthält, die in einem beobachtbaren Array eingeschlossen sind, sodass Knockout.js nachverfolgen kann, wann Elemente hinzugefügt und entfernt werden. Bevor wir jedoch mit dem Bearbeiten der Objekte beginnen, aktualisieren wir unsere Ansicht, damit wir den Inhalt des Objekts sehen können Einkaufswagen Eigentum. Unter der

Tag, fügen Sie Folgendes hinzu:

 
Produkt Preis

Dies ist eine typische HTML 5-Tabelle, die eine Spalte für Produktnamen und eine weitere für Produktpreise enthält. In diesem Beispiel wird auch eine neue Bindung eingeführt für jeden. Wenn Knockout.js aufeinander trifft foreach: shoppingCart, Es durchläuft jedes Element im ViewModel Einkaufswagen Eigentum. Jedes Markup innerhalb der Schleife wird im Kontext jedes Elements ausgewertet, sodass text: name tatsächlich auf shoppingCart [i] .name verweist. Das Ergebnis ist eine Tabelle mit Artikeln neben ihren Preisen:

Abbildung 14: Screenshot der gerenderten Produktliste

Die Details der für jeden verbindlich sind außerhalb des Gültigkeitsbereichs dieser Lektion. In der nächsten Lektion wird ausführlich über foreach diskutiert. Außerdem werden die anderen Kontrollflussbindungen von Knockout.js vorgestellt. Kommen wir jetzt zu den beobachtbaren Arrays.

Elemente hinzufügen

Bei der Verwendung beobachtbarer Arrays muss Knockout.js die Ansicht synchronisieren, wenn Elemente hinzugefügt oder entfernt werden. Zum Beispiel können wir in ViewModel eine Methode definieren, die ein neues Element hinzufügt.

 this.addProduct = function () this.shoppingCart.push (neues Produkt ("More Beer", 10.99)); ;

Dann können wir eine Schaltfläche erstellen, um die Methode aufzurufen, sodass Elemente zur Laufzeit hinzugefügt werden können und Knockout.js die Liste auf dem neuesten Stand hält. Fügen Sie neben dem Checkout-Button im Ansichtscode Folgendes hinzu:

 

Wenn Sie auf diese Schaltfläche klicken, wird das ViewModel angezeigt Produkt hinzufügen() Methode wird ausgeführt. Und seit Einkaufswagen Ist ein beobachtbares Array, fügt Knockout.js ein anderes ein Element, um das neue Element anzuzeigen. Wenn Knockout.js Listenelemente wie diese verfolgt, ist dies weniger fehleranfällig als der Versuch, das Element manuell zu aktualisieren

wann immer wir das zugrunde liegende Array ändern.

Es ist auch wert darauf hinzuweisen, dass Knockout.js immer das macht minimal Anzahl der erforderlichen Änderungen zur Synchronisierung der Benutzeroberfläche. Anstatt die gesamte Liste jedes Mal neu zu generieren, wenn ein Element hinzugefügt oder entfernt wird, verfolgt Knockout.js, welche Teile des DOM betroffen sind, und aktualisiert nur diese Elemente. Diese integrierte Optimierung ermöglicht es, Ihre Anwendung auf Hunderte oder sogar Tausende von Elementen zu skalieren, ohne die Reaktionsfähigkeit zu beeinträchtigen.

Elemente löschen

In ähnlicher Weise kann Knockout.js auch Elemente aus einem beobachtbaren Array über das Symbol löschen Löschen() Methode. Fügen Sie innerhalb der PersonViewModel-Definition eine weitere Methode zum Entfernen von Elementen hinzu:

 this.removeProduct = Funktion (Produkt) this.shoppingCart.remove (Produkt); ;

Fügen Sie dann für jedes Element in der Schaltfläche eine Schaltfläche zum Löschen hinzu

Schleife:

 

Weil wir im sind für jeden In diesem Zusammenhang mussten wir die $ root Referenz, um auf unser ViewModel zuzugreifen, anstatt auf das aktuelle Element in der Schleife. Wenn wir versuchen, removeProduct () ohne diese Referenz aufzurufen, hätte Knockout.js versucht, die Methode für die Product-Klasse aufzurufen, die nicht vorhanden ist. Alle verfügbaren Bindungskontexte für foreach werden in der nächsten Lektion behandelt.

Die Tatsache, dass wir in einer für jeden Schleife verwirrt auch die diese referenz in removeProduct (), klicken Sie also auf a Löschen Die Schaltfläche wirft tatsächlich einen TypeError aus. Wir können einen üblichen JavaScript-Trick verwenden, um diese Art von Problemen zu beheben. Weisen Sie oben in der PersonViewModel-Definition eine neue Variable namens self zu:

 Funktion PersonViewModel () var self = this;… 

Dann benutze selbst anstatt diese in der removeProduct () -Methode:

 this.removeProduct = Funktion (Produkt) self.shoppingCart.remove (Produkt); ;

Sie sollten jetzt in der Lage sein, unser beobachtbares Array mit der Bier hinzufügen und Löschen Tasten. Beachten Sie auch, dass Knockout.js automatisch das aktuelle Element in der Schleife als ersten Parameter zu hinzufügt removeProduct ().

Gegenstände zerstören

Das Löschen() Diese Methode ist für die Bearbeitung von Listen in Echtzeit hilfreich, kann sich jedoch als problematisch erweisen, wenn Sie versuchen, Daten vom ViewModel an ein serverseitiges Skript zu senden.

Stellen Sie sich beispielsweise die Aufgabe vor, den Einkaufswagen jedes Mal in einer Datenbank zu speichern, wenn der Benutzer einen Artikel hinzugefügt oder gelöscht hat. Mit Löschen(), Der Artikel wird entfernt sofort, Sie können Ihrem Server also nur die neue Liste als Ganzes senden. Es ist nicht möglich zu bestimmen, welche Elemente hinzugefügt oder entfernt wurden. Sie müssen entweder die gesamte Liste speichern oder manuell den Unterschied zwischen der in der Datenbank gespeicherten vorherigen Version und der neuen aus der AJAX-Anforderung übergebenen ermitteln.

Keine dieser Optionen ist besonders effizient, zumal Knockout.js genau weiß, welche Elemente entfernt wurden. Um dieser Situation abzuhelfen, umfassen beobachtbare Arrays a zerstören() Methode. Versuchen Sie, PersonViewModel.removeProduct () wie folgt zu ändern:

 this.removeProduct = Funktion (Produkt) self.shoppingCart.destroy (Produkt); alert (self.shoppingCart (). length); ;

Nun, wenn Sie auf klicken Löschen Schaltfläche Knockout.js Gewohnheit Entfernen Sie das Element aus dem darunter liegenden Array. Dies wird in der Warnmeldung angezeigt, die dies tun sollte nicht verringern, wenn Sie auf "Entfernen" klicken. Anstatt die Liste zu ändern, zerstören() Methode fügt ein _zerstören Eigenschaft an das Produkt und setzt es auf true. Sie können diese Eigenschaft anzeigen, indem Sie eine weitere Warnmeldung hinzufügen:

 Alarm (Produkt.Zerstörung);

Das _zerstören Diese Eigenschaft ermöglicht das Durchsuchen einer beobachtbaren Liste und das Auslesen nur der gelöschten Elemente. Dann können Sie senden nur diese Elemente zu einem serverseitigen Skript, das gelöscht werden soll. Dies ist eine wesentlich effizientere Methode zum Verwalten von Listen, wenn Sie mit AJAX-Anforderungen arbeiten.

Notiere dass der für jeden Die Schleife ist sich dieser Konvention bewusst und entfernt immer noch die zugehörige

Element aus der Ansicht, auch wenn das Element im darunter liegenden Array verbleibt.

Andere Array-Methoden

Intern beobachtbare Arrays sind wie normale beobachtbare Eigenschaften, außer dass sie durch ein natives JavaScript-Array anstelle einer Zeichenfolge, einer Zahl oder eines Objekts unterstützt werden. Wie normale Observables können Sie auf den zugrunde liegenden Wert zugreifen, indem Sie das Observable-Array ohne Eigenschaften aufrufen:

 this.debugItems = function () var message = ""; var nativeArray = this.shoppingCart (); für (var i = 0; i 

Wenn Sie diese Methode aufrufen, werden die Elemente der nativen Liste durchlaufen, und Sie erhalten auch Zugriff auf die nativen JavaScript-Array-Methoden wie drücken(), Pop(), shift (), sort () usw.

Knockout.js definiert jedoch seine eigene Versionen dieser Methoden für das Observable-Array-Objekt. Zum Beispiel haben wir früher in dieser Lektion verwendet shoppingCart.push () einen Artikel anstelle von hinzufügen shoppingCart (). push (). Ersteres ruft die Version von Knockout.js auf, und letzteres ruft push () für das native JavaScript-Array auf.

Es ist normalerweise eine viel bessere Idee, die Array-Methoden von Knockout.js zu verwenden, anstatt direkt auf das zugrunde liegende Array zuzugreifen, da Knockout.js die abhängigen Ansichtskomponenten automatisch aktualisiert. Es folgt die vollständige Liste der beobachtbaren Array-Methoden, die von Knockout.js bereitgestellt werden. Die meisten von ihnen verhalten sich genauso wie ihre nativen JavaScript-Pendants.

  • drücken()
  • Pop()
  • nicht verschieben()
  • Verschiebung()
  • Scheibe()
  • Löschen()
  • alles entfernen()
  • zerstören()
  • Alle zerstören()
  • Sortieren()
  • rückgängig gemacht()
  • Index von()

Zusammenfassung

In dieser Lektion haben wir gesehen, wie berechnete Observable verwendet werden können, um normale Observables zu zusammengesetzten Eigenschaften zu kombinieren, die Knockout.js verfolgen kann. Wir haben auch mit beobachtbaren Arrays gearbeitet, mit denen Knockout.js Datenlisten im ViewModel mit HTML-Komponenten synchronisieren kann.

Atomare, berechnete und Array-Observables bieten alle zugrunde liegenden Datentypen, die Sie für eine typische Benutzeroberfläche benötigen. Berechnete Observables und Observable Arrays machen Knockout.js zu einer hervorragenden Option für das Rapid Prototyping. Damit können Sie all Ihre komplexen Funktionen an einen Ort stellen und Knockout.js sich um den Rest kümmern.

Es wäre zum Beispiel trivial, ein berechnetes Beobachtungsobjekt zu erstellen, das den Gesamtpreis jedes Artikels im berechnet Einkaufswagen Liste und zeigt sie am unteren Rand der Seite an. Wenn Sie diese Funktion erstellt haben, können Sie sie wiederverwenden irgendwo Sie benötigen den Gesamtpreis (z. B. eine AJAX-Anforderung), indem Sie einfach auf eine ViewModel-Eigenschaft zugreifen.

Die nächste Lektion führt Kontrollflussbindungen ein. Das für jeden Die Bindung, die wir in dieser Lektion verwendet haben, ist wahrscheinlich das am häufigsten verwendete Steuerelement für die Steuerung, aber Knockout.js enthält auch einige weitere Bindungen für die fein abgestimmte Steuerung unserer HTML-Ansichtskomponenten.

Diese Lektion repräsentiert ein Kapitel aus Knockout Prägnant, ein kostenloses eBook aus dem Team von Syncfusion.