Knockout Observables

Vi har sett hur observerbara egenskaper låter Knockout.js automatiskt uppdatera HTML-element när underliggande data ändras, men det här är bara början på verktyget. Knockout.js kommer också med ytterligare två sätt att exponera ViewModel egenskaper: beräknade observerbara och observerbara arrays. Tillsammans öppnar dessa en helt ny värld av möjligheter till datadriven användargränssnitt.

Beräknade observerbara uppgifter Låt dig skapa egenskaper som dynamiskt genereras. Det betyder att du kan kombinera flera normala observerbara objekt i en enda egenskap, och Knockout.js kommer fortfarande att hålla vyn aktuell när någon av de underliggande värdena ändras.

Figur 12: En beräknad observerbar beroende på två normala observerbara data

Observable arrays kombinera kraften i Knockout.js observerbarhet med inbyggda JavaScript-arrays. Som inbyggda arrays innehåller de listor över objekt som du kan manipulera. Men eftersom de är observerbara uppdaterar Knockout.js automatiskt alla associerade HTML-element när saker läggs till eller tas bort.

Figur 13: En observerbar grupp som innehåller andra ViewModels

Möjligheten att kombinera observerbarhet, tillsammans med förmågan att arbeta med listor över objekt, ger alla datastrukturer som du behöver i en ViewModel. Denna lektion introducerar båda ämnena med ett enkelt kundvagnsgränssnitt.


Beräknade observables

Först börjar vi med en enkel beräknad observerbar. Under förnamn och efternamn observerbarhet i PersonViewModel, skapa fullnamnet beräknat observerbart:

 this.fullName = ko.computed (funktion () returnera detta.firstName () + "" + this.lastName ();, detta);

Detta definierar en anonym funktion som returnerar personens fullständiga namn närhelst PersonViewModel.fullName är tillgänglig. Dynamiskt generera fullständigt namn från befintliga komponenter (förnamn och förnamn) hindrar oss från att lagra överflödiga data, men det är bara hälften av slaget. Vi måste överföra denna funktion till ko.computed () för att skapa en beräknad observerbar. Detta berättar Knockout.js att det behöver uppdatera alla HTML-element som är bundna till fullName-egenskapen när antingen förnamn eller förnamn ändras.

Låt oss se till att vår beräknade observerbara fungerar genom att binda "John's Shopping Cart" -linjen till fullständiga namn istället för förnamn:

 

s kundvagn

Nu ska din sida läsa "John Smiths kundvagn". Låt oss sedan se till att Knockout.js håller det här HTML-elementet synkroniserat när vi ändrar en av de underliggande egenskaperna. Efter bindande en förekomst av PersonViewModel, försök ändra sin firstName-egenskap:

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

Detta bör ändra linjen till "Mary Smiths kundvagn". Återigen, kom ihåg att läsning eller inställning observerbarhet ska göras med funktionssamtal, inte uppdraget (=) operatör.

Beräknade observerbarheter ger många av samma fördelar som Knockout.js automatiska synkronisering av vyn. I stället för att hålla reda på vilka egenskaper som är beroende av andra delar av ViewModel, kan beräknade observerbarheter bygga din applikation kring atomegenskaper och delegera beredskapsspårning till Knockout.js.


Observable Arrays

Observable arrayer låter Knockout.js spåra listor över objekt. Vi utforskar detta genom att skapa en sida för kundvagnen för våra användare. Först måste vi skapa ett anpassat objekt för att representera produkter. Överst på vårt manus, innan du definierar PersonViewModel, lägg till följande objektdefinition:

 funktion Produkt (namn, pris) this.name = ko.observable (namn); this.price = ko.observable (pris); 

Detta är bara ett enkelt dataobjekt för att lagra några egenskaper. Observera att det är möjligt att ge observerbara egenskaper för flera objekt, och Knockout.js hanterar alla interdependenser på egen hand. Det är med andra ord möjligt att skapa relationer mellan flera olika ViewModels i en enda applikation.

Därefter kommer vi att skapa några exempel på vårt nya Produkt klass och lägg till dem i användarens virtuella kundvagn. Insidan av PersonViewModel, definiera en ny observerbar egenskap som heter shoppingCart:

 this.shoppingCart = ko.observableArray ([ny produkt ("öl", 10.99), ny produkt ("Brats", 7,99), ny produkt ("bullar", 1,49)]);

Detta är en inbyggd JavaScript-uppsättning som innehåller tre produkter insvept i en observerbar array så Knockout.js kan spåra när objekt läggs till och tas bort. Men innan vi börjar manipulera objekten, låt oss uppdatera vår syn så att vi kan se innehållet i kundvagn fast egendom. Under

tagg, lägg till följande:

 
Produkt Pris

Detta är en typisk HTML 5-tabell som innehåller en kolumn för produktnamn och en annan för produktpriser. Detta exempel introducerar också en ny bindning som heter för varje. När Knockout.js möter förhand: shoppingkarta, det loopar genom varje objekt i ViewModel s kundvagn fast egendom. Varje markering inuti slingan utvärderas i sammanhanget för varje objekt, så text: namn hänvisar faktiskt till shoppingCart [i] .name. Resultatet är en tabell med varor utöver sina priser:

Figur 14: Skärmdump av den gjorda produktlistan

Detaljerna i för varje bindande ligger utanför ramen för denna lektion. Nästa lektion ger en djupgående diskussion om förhand, och det introducerar också Knockout.js andra kontrollflödesbindningar. För nu, låt oss komma tillbaka till observerbara arrays.

Lägga till objekt

Hela punkten att använda observerbara arrays är att låta Knockout.js synkronisera vyn när vi lägger till eller tar bort objekt. Till exempel kan vi definiera en metod på vår ViewModel som lägger till ett nytt objekt, som så:

 this.addProduct = function () this.shoppingCart.push (ny produkt ("More Beer", 10.99)); ;

Då kan vi skapa en knapp för att ringa metoden så att vi kan lägga till objekt vid körning och se Knockout.js hålla listan uppdaterad. Lägg till följande vid sidan av kassan i visningskoden:

 

När du klickar på den här knappen, är ViewModel s addProduct () Metoden exekveras. Och sedan kundvagn är en observerbar grupp, Knockout.js infogar en annan element för att visa det nya objektet. Att låta Knockout.js hålla reda på listobjekt som detta är mycket mindre felaktigt än att försöka manuellt uppdatera

när vi ändrar den underliggande gruppen.

Det är också värt att påpeka att Knockout.js alltid gör minimal mängd ändringar som behövs för att synkronisera användargränssnittet. Istället för att regenerera hela listan varje gång ett objekt läggs till eller tas bort spårar Knockout.js vilka delar av DOM som påverkas och uppdateringar endast dessa element. Den här inbyggda optimeringen gör det möjligt att skala upp din ansökan till hundratals eller till och med tusentals objekt utan att offra på respons.

Radera objekt

På samma sätt kan Knockout.js också ta bort objekt från en observerbar array via ta bort() metod. Inne i definitionen PersonViewModel lägger du till en annan metod för att ta bort objekt:

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

Lägg sedan till en raderingsknapp för varje objekt i

slinga:

 

Eftersom vi är i för varje sammanhang, vi var tvungna att använda $ rot hänvisning till åtkomst till vår ViewModel istället för det aktuella objektet i slingan. Om vi ​​försökte ringa removeProduct () utan denna referens skulle Knockout.js ha försökt ringa metoden i produktklassen, som inte existerar. Alla tillgängliga bindande sammanhang för föreach omfattas av nästa lektion.

Att vi är i en för varje loop slår också upp detta referens i removeProduct (), så klicka på a Ta bort knappen kommer faktiskt att kasta en TypeError. Vi kan använda ett gemensamt JavaScript-trick för att lösa dessa typer av räckviddsproblem. Överst i PersonViewModel-definitionen, tilldela den här till en ny variabel som heter själv:

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

Använd sedan själv istället för detta i methoden removeProduct ():

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

Du borde nu kunna manipulera vår observerbara array med Lägg till öl och Ta bort knappar. Observera också att Knockout.js automatiskt lägger till det aktuella objektet i slingan som den första parametern till removeProduct ().

Förstöra objekt

De ta bort() Metoden är användbar för realtids manipulering av listor, men det kan vara besvärligt när du börjar försöka skicka data från ViewModel till ett serverns script.

Tänk på att uppgiften är att spara kundvagnen till en databas varje gång användaren lagt till eller raderar ett objekt. Med ta bort(), objektet är borttaget omedelbart, så allt du kan göra är att skicka din server till den nya listan i sin helhet - det är omöjligt att bestämma vilka föremål där läggas till eller tas bort. Du måste antingen spara hela listan eller manuellt räkna ut skillnaden mellan den tidigare versionen som lagrats i databasen och den nya som skickades in från AJAX-förfrågan.

Ingen av dessa alternativ är särskilt effektiv, särskilt med tanke på Knockout.js vet exakt vilka föremål som tagits bort. För att avhjälpa denna situation innefattar observabla arrays a förstöra() metod. Försök ändra PersonViewModel.removeProduct () till följande:

 this.removeProduct = function (product) self.shoppingCart.destroy (produkt); alert (self.shoppingCart () längd.); ;

Nu när du klickar på Ta bort knappen, Knockout.js vana ta bort objektet från den underliggande matrisen. Detta visas i varningsmeddelandet, vilket ska inte minska när du klickar på "Ta bort." I stället för att ändra listan, förstöra() Metoden lägger till a _förstöra egendom till produkten och sätter den till sant. Du kan visa den här egenskapen genom att lägga till ett annat varningsmeddelande:

 alert (product._destroy);

De _förstöra egendom gör det möjligt att sortera igenom en observerbar lista och dra ut endast poster som har tagits bort. Då kan du skicka endast de objekten till ett serverns script för att raderas. Detta är ett mycket effektivare sätt att hantera listor när man arbetar med AJAX-förfrågningar.

Observera att för varje loop är medveten om denna konvention och tar bort de associerade

element från vyn, trots att objektet förblir i den underliggande gruppen.

Andra Array Metoder

Internt observerbara arrays är precis som normala observerbara egenskaper, förutom att de stöds av ett inbyggt JavaScript-array istället för en sträng, ett tal eller ett objekt. Precis som normala observerbara data kan du komma åt det underliggande värdet genom att ringa det observerbara systemet utan några egenskaper:

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

Om du ringer till den här metoden kommer du att springa igenom objektets objekt, och det ger också tillgång till de inbyggda JavaScript-array-metoderna som tryck(), pop(), skift (), sortera (), etc..

Dock definierar Knockout.js sin egen versioner av dessa metoder på det observerbara arrayobjektet. Till exempel tidigare i den här lektionen använde vi shoppingCart.push () att lägga till ett objekt istället för Shoppingcart (). Tryck (). Den tidigare kallar Knockout.js 'version, och den senare kallar push () på den inbyggda JavaScript-matrisen.

Det är vanligtvis en mycket bättre idé att använda Knockout.js array metoder istället för att komma åt den underliggande arrayen direkt eftersom det tillåter Knockout.js att automatiskt uppdatera alla beroende bilder. Den kompletta listan över observerbara array-metoder som tillhandahålls av Knockout.js följer. De flesta av dessa agerar exakt som deras inbyggda JavaScript-motsvarigheter.

  • tryck()
  • pop-()
  • unshift()
  • flytta()
  • skiva()
  • ta bort()
  • ta bort alla()
  • förstöra()
  • destroyAll()
  • sortera()
  • omvänd()
  • index för()

Sammanfattning

I denna lektion såg vi hur beräknade observerbarheter kan användas för att kombinera normala observerbara ämnen i sammansatta egenskaper som Knockout.js kan spåra. Vi har också arbetat med observerbara arrayer, vilket är ett sätt för Knockout.js att synkronisera listor med data i ViewModel med HTML-komponenter.

Tillsammans tillhandahåller atomära, beräknade och array observables alla de underliggande datatyperna du någonsin behöver för ett typiskt användargränssnitt. Beräknade observerbarheter och observerbara arrays gör Knockout.js till ett utmärkt alternativ för snabb prototypning. De låter dig placera all din komplexa funktionalitet enstans, och sedan låta Knockout.js ta hand om resten.

Det skulle till exempel vara trivialt att skapa en beräknad observerbar som beräknar totalpriset för varje objekt i kundvagn lista och visar den längst ner på sidan. När du har skapat den funktionen kan du återanvända den var som helst du behöver det totala priset (t.ex. en AJAX-förfrågan) bara genom att öppna en ViewModel-egenskap.

Nästa lektion introducerar kontrollflödesbindningar. De för varje bindning som vi använde i den här lektionen är förmodligen det vanligaste kontrollflödesverktyget, men Knockout.js innehåller också några fler bindningar för finkorrigerad kontroll över våra HTML-visningskomponenter.

Denna lektion representerar ett kapitel från Knockout Succinctly, en gratis eBook från laget på Syncfusion.