Knockout Observables

We hebben gezien hoe waarneembare eigenschappen Knockout.js automatisch HTML-elementen laten bijwerken wanneer onderliggende gegevens veranderen, maar dit is slechts het begin van hun hulpprogramma. Knockout.js biedt ook nog twee manieren om ViewModel-eigenschappen te tonen: berekende observaties en waarneembare matrices. Samen openen deze een hele nieuwe wereld van mogelijkheden voor data-gestuurde gebruikersinterfaces.

Berekende observabelen kunt u eigenschappen maken die dynamisch worden gegenereerd. Dit betekent dat u verschillende normale waarnemingen kunt combineren in één enkele eigenschap, en Knockout.js zal het overzicht nog steeds actueel houden wanneer een van de onderliggende waarden verandert.

Figuur 12: Een berekend waarneembaar afhankelijk van twee normale waarnemingen

Waarneembare matrices combineer de kracht van Knockout.js 'observables met native JavaScript-arrays. Net als bij native arrays bevatten ze lijsten met items die u kunt bewerken. Maar aangezien ze waarneembaar zijn, werkt Knockout.js automatisch alle bijbehorende HTML-elementen bij wanneer items worden toegevoegd of verwijderd.

Figuur 13: Een waarneembare array die andere ViewModels bevat

De mogelijkheid om observabelen te combineren met de mogelijkheid om met lijsten met items te werken, biedt alle gegevensstructuren die u in een ViewModel nodig hebt. Deze les introduceert beide onderwerpen met een eenvoudige interface voor het winkelwagentje.


Berekende Observables

Eerst zullen we beginnen met een eenvoudige berekende waarneembare. Onder de Voornaam en achternaam observeables in PersonViewModel, maak de fullName berekend waarneembaar:

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

Dit definieert een anonieme functie die de volledige naam van de persoon altijd retourneert PersonViewModel.fullName is toegankelijk. Dynamisch genereren van de volledige naam van de bestaande componenten (Voornaam en lastName) voorkomt dat we redundante gegevens opslaan, maar dat is slechts de helft van de strijd. We moeten deze functie doorgeven aan ko.computed () om een ​​berekende waarneembaar te maken. Dit vertelt Knockout.js dat het HTML-elementen moet bijwerken die zijn gebonden aan de eigenschap fullName wanneer firstName of lastName wordt gewijzigd.

Laten we ervoor zorgen dat onze berekende waarneembare werken werken door de "John's Shopping Cart" -lijn aan te binden voor-en achternaam in plaats van firstName:

 

Winkelwagen

Nu moet uw pagina "John Smith's winkelwagen" lezen. Laten we er vervolgens voor zorgen dat Knockout.js dit HTML-element synchroon houdt wanneer we een van de onderliggende eigenschappen wijzigen. Na het binden van een instantie van PersonViewModel, probeer de eigenschap firstName te wijzigen:

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

Dit zou de regel moeten veranderen in "Mary Smith's winkelwagen." Nogmaals, onthoud dat het lezen of instellen van waarnemingen gedaan moet worden met functieaanroepen, niet met de opdracht (=) operator.

Berekende observaties bieden veel van dezelfde voordelen als de automatische synchronisatie van de weergave door Knockout.js. In plaats van dat u bijhoudt welke eigenschappen afhankelijk zijn van andere delen van het ViewModel, kunt u met behulp van computationele waarnemingen uw toepassing rond atomaire eigenschappen bouwen en afhankelijkheidsregistratie delegeren naar Knockout.js.


Waarneembare reeksen

Waarneembare matrices laten Knockout.js lijsten met items bijhouden. We zullen dit verkennen door een displaypagina voor de winkelwagen voor onze gebruiker te maken. Eerst moeten we een aangepast object maken om producten te vertegenwoordigen. Aan de bovenkant van ons script, voor het definiëren PersonViewModel, voeg de volgende objectdefinitie toe:

 functie Product (naam, prijs) this.name = ko.observable (name); this.price = ko. waarneembaar (prijs); 

Dit is slechts een eenvoudig data-object om een ​​paar eigenschappen op te slaan. Merk op dat het mogelijk is om meerdere objecten waarneembare eigenschappen te geven, en Knockout.js beheert alle onderlinge afhankelijkheden op zichzelf. Met andere woorden, het is mogelijk om relaties te creëren tussen meerdere ViewModels in een enkele applicatie.

Vervolgens gaan we een paar voorbeelden van ons nieuw maken Artikel klasse en voeg ze toe aan de virtuele winkelwagen van de gebruiker. Binnenkant van PersonViewModel, een nieuwe waarneembare eigenschap definiëren, genaamd shoppingCart:

 this.shoppingCart = ko.observableArray ([nieuw product ("Beer", 10.99), nieuw product ("Brats", 7.99), nieuw product ("Buns", 1.49)]);

Dit is een native JavaScript-array met drie producten verpakt in een waarneembare array, zodat Knockout.js kan bijhouden wanneer items worden toegevoegd en verwijderd. Maar voordat we beginnen met het manipuleren van de objecten, laten we onze weergave bijwerken zodat we de inhoud van de objecten kunnen bekijken winkelwagen eigendom. Onder de

tag, voeg het volgende toe:

 
Artikel Prijs

Dit is een typische HTML 5-tabel met een kolom voor productnamen en een andere voor productprijzen. Dit voorbeeld introduceert ook een nieuwe binding genaamd foreach. Wanneer Knockout.js tegenkomt foreach: shoppingCart, het lus door elk item in de ViewModel's winkelwagen eigendom. Elke opmaak binnen in de lus wordt geëvalueerd in de context van elk item, dus tekst: naam verwijst in feite naar shoppingCart [i] .name. Het resultaat is een tabel met items naast hun prijzen:

Figuur 14: Schermafbeelding van de weergegeven productlijst

De details van de foreach binding valt buiten het bereik van deze les. De volgende les biedt een diepgaande discussie over foreach, en het introduceert ook Knockout.js 'andere besturingsstroombindingen. Laten we voor nu teruggaan naar waarneembare matrices.

Items toevoegen

Het hele punt van het gebruik van waarneembare matrices is om Knockout.js de weergave te laten synchroniseren wanneer we items toevoegen of verwijderen. We kunnen bijvoorbeeld een methode op ons ViewModel definiëren die een nieuw item toevoegt, zoals:

 this.addProduct = function () this.shoppingCart.push (nieuw product ("More Beer", 10.99)); ;

Vervolgens kunnen we een knop maken om de methode te gebruiken, zodat we tijdens runtime items kunnen toevoegen en Knockout.js de lijst up-to-date kunnen houden. Voeg naast de kassaknop in de viewcode het volgende toe:

 

Wanneer u op deze knop klikt, zijn de ViewModel's addProduct () methode wordt uitgevoerd. En sindsdien winkelwagen is een waarneembare array, Knockout.js voegt er een andere in element om het nieuwe item weer te geven. Door Knockout.js de lijstitems zoals deze te laten volgen, is dit veel minder foutgevoelig dan het proberen handmatig bijwerken van de

telkens wanneer we de onderliggende array wijzigen.

Het is ook de moeite waard om erop te wijzen dat Knockout.js altijd de minimaal aantal wijzigingen dat nodig is om de gebruikersinterface te synchroniseren. In plaats van de volledige lijst te regenereren telkens wanneer een item wordt toegevoegd of verwijderd, houdt Knockout.js bij welke delen van de DOM worden beïnvloed en updates enkel en alleen die elementen. Deze ingebouwde optimalisatie maakt het mogelijk om uw toepassing op te schalen naar honderden of zelfs duizenden items zonder in te boeten op reactievermogen.

Items verwijderen

Evenzo kan Knockout.js ook items uit een waarneembare array verwijderen via de verwijderen() methode. Binnen de PersonViewModel-definitie voegt u een andere methode toe om items te verwijderen:

 this.removeProduct = function (product) this.shoppingCart.remove (product); ;

Voeg vervolgens een verwijderknop toe voor elk item in de

lus:

 

Omdat we in de foreach context, we moesten de $ wortel verwijzing naar ons ViewModel in plaats van het huidige item in de lus. Als we zonder deze verwijzing removeProduct () proberen aan te roepen, zou Knockout.js geprobeerd hebben de methode op te roepen in de klasse Product, die niet bestaat. Alle beschikbare bindende contexten voor foreach worden behandeld in de volgende les.

Het feit dat we in een foreach loop maakt ook het deze verwijzing in removeProduct (), dus klikken op a Verwijderen knop gooit eigenlijk een TypeError. We kunnen een algemene JavaScript-truc gebruiken om dit soort scopekwesties op te lossen. Bovenaan de PersonViewModel-definitie wijst u dit toe aan een nieuwe variabele met de naam zelf:

 function PersonViewModel () var self = this; ... 

Gebruik dan zelf in plaats van deze in de methode removeProduct ():

 this.removeProduct = function (product) self.shoppingCart.remove (product); ;

Je zou nu onze waarneembare array met de kunnen manipuleren Voeg bier toe en Verwijderen toetsen. Merk ook op dat Knockout.js automatisch het huidige item in de lus als de eerste parameter toevoegt aan removeProduct ().

Artikelen vernietigen

De verwijderen() methode is handig voor het in realtime manipuleren van lijsten, maar het kan lastig zijn als je eenmaal probeert om gegevens van het ViewModel naar een server-side script te verzenden.

Denk bijvoorbeeld aan de taak om het winkelwagentje in een database op te slaan telkens wanneer de gebruiker een item heeft toegevoegd of verwijderd. Met verwijderen(), het item is verwijderd per direct, dus alles wat u kunt doen, is uw server de nieuwe lijst in zijn geheel verzenden - het is onmogelijk om te bepalen welke items zijn toegevoegd of verwijderd. U moet ofwel de volledige lijst opslaan, of handmatig het verschil berekenen tussen de vorige versie die in de database is opgeslagen en de nieuwe die is doorgegeven van het AJAX-verzoek.

Geen van deze opties is bijzonder efficiënt, vooral als u weet dat Knockout.js precies weet welke items zijn verwijderd. Om deze situatie te verhelpen, bevatten waarneembare matrices een vernietigen() methode. Probeer PersonViewModel.removeProduct () te wijzigen in het volgende:

 this.removeProduct = function (product) self.shoppingCart.destroy (product); alert (self.shoppingCart () lengte.); ;

Nu wanneer u op klikt Verwijderen knop, Knockout.js zal niet verwijder het item uit de onderliggende array. Dit wordt weergegeven in het waarschuwingsbericht, dat zou moeten niet verminderen wanneer u op "Verwijderen" klikt. In plaats van de lijst te wijzigen, wordt de vernietigen() methode voegt een toe _vernietigen eigendom van het product en stelt het in op waar. U kunt deze eigenschap weergeven door een ander waarschuwingsbericht toe te voegen:

 alert (product._destroy);

De _vernietigen eigenschap maakt het mogelijk om een ​​waarneembare lijst te sorteren en alleen items te verwijderen die zijn verwijderd. Vervolgens kunt u verzenden enkel en alleen die items naar een server-side script worden verwijderd. Dit is een veel efficiëntere manier om lijsten te beheren bij het werken met AJAX-aanvragen.

Merk op dat de foreach lus is op de hoogte van deze conventie en verwijdert nog steeds de bijbehorende

element uit de weergave, ook al blijft het item in de onderliggende array.

Andere matrixmethoden

Intern zijn waarneembare matrices net als normale waarneembare eigenschappen, behalve dat ze worden ondersteund door een native JavaScript-array in plaats van een tekenreeks, getal of object. Zoals normale waarnemingen, kunt u toegang krijgen tot de onderliggende waarde door de waarneembare array zonder eigenschappen te gebruiken:

 this.debugItems = function () var message = ""; var nativeArray = this.shoppingCart (); for (var i = 0; i 

Als u deze methode aanroept, worden de items van de native lijst doorlopen en wordt ook toegang geboden tot de JavaScript-array-methoden zoals Duwen(), knal(), shift (), sort (), enz.

Echter, Knockout.js definieert zijn eigen versies van deze methoden op het waarneembare array-object. We hebben bijvoorbeeld eerder in deze les gebruikt shoppingCart.push () om een ​​item toe te voegen in plaats van Winkelwagen (). push (). De vorige roept de versie van Knockout.js aan, en de laatste roept push () op de native JavaScript-array.

Het is meestal een veel beter idee om de array-methoden van Knockout.js te gebruiken in plaats van rechtstreeks toegang te krijgen tot de onderliggende array, omdat het Knockout.js toestaat automatisch alle afhankelijke view-componenten bij te werken. De volledige lijst van waarneembare array-methoden die door Knockout.js worden aangeboden, volgt. De meeste van deze werken precies zoals hun native JavaScript-tegenhangers.

  • Duwen()
  • knal()
  • unshift()
  • verschuiving()
  • plak()
  • verwijderen()
  • Verwijder alles()
  • vernietigen()
  • destroyAll()
  • soort()
  • omgekeerd()
  • index van()

Samenvatting

In deze les hebben we gezien hoe berekende observaties kunnen worden gebruikt om normale waarnemingen te combineren in samengestelde eigenschappen die Knockout.js kan bijhouden. We hebben ook gewerkt met waarneembare matrices, wat een manier is voor Knockout.js om lijsten met gegevens in het ViewModel te synchroniseren met HTML-componenten.

Samen bieden atomaire, berekende en arrayobservaties alle onderliggende gegevenstypes die u ooit nodig zult hebben voor een typische gebruikersinterface. Berekende observaties en waarneembare matrices maken Knockout.js een geweldige optie voor snelle prototyping. Ze laten je al je complexe functionaliteit een plaats geven en laten Knockout.js voor de rest zorgen.

Het zou bijvoorbeeld triviaal zijn om een ​​berekende waarneembaar te maken die de totale prijs berekent van elk item in de winkelwagen lijst en geeft deze onderaan de pagina weer. Zodra u die functionaliteit hebt gemaakt, kunt u deze opnieuw gebruiken overal u hebt de totale prijs nodig (bijvoorbeeld een AJAX-aanvraag) door alleen toegang te krijgen tot een ViewModel-eigenschap.

De volgende les introduceert besturingsstroombindingen. De foreach binding die we in deze les hebben gebruikt, is waarschijnlijk de meest gebruikte regelstroommodel, maar Knockout.js bevat ook nog enkele extra bindingen voor een fijnmazig beheer van onze HTML-viewcomponenten.

Deze les vertegenwoordigt een hoofdstuk van Knockout bondig, een gratis eBoek van het team van Syncfusion.