Knockout Observables

Vi har sett hvordan observerbare egenskaper lar Knockout.js automatisk oppdatere HTML-elementer når underliggende data endres, men dette er bare begynnelsen på verktøyet deres. Knockout.js kommer også med to andre måter å eksponere ViewModel egenskaper på: Beregnede observerbare og observerbare arrayer. Sammen åpner disse opp en helt ny verden av muligheter for data-drevne brukergrensesnitt.

Beregnede observerbare data la deg lage egenskaper som er dynamisk generert. Dette betyr at du kan kombinere flere vanlige observerbare objekter i en enkelt eiendom, og Knockout.js vil fortsatt holde visningen oppdatert når noen av de underliggende verdiene endres.

Figur 12: En beregnbar observerbar avhengig av to normale observerbare data

Observable arrayer kombinere kraften til Knockout.js observerbare objekter med innfødte JavaScript-arrays. Som innfødte arrays inneholder de lister over elementer som du kan manipulere. Men siden de er observerbare, oppdaterer Knockout.js automatisk eventuelle tilknyttede HTML-elementer når ting legges til eller fjernes.

Figur 13: Et observerbart array som inneholder andre ViewModels

Evnen til å kombinere observerbare data, sammen med evnen til å arbeide med lister over elementer, gir alle datastrukturene du trenger i en ViewModel. Denne leksjonen introduserer begge temaene med et enkelt handlekurvgrensesnitt.


Beregnede observasjoner

Først begynner vi med en enkel beregningsbar observerbar. Under fornavn og etternavn observables i PersonViewModel, opprett fullName beregnet observerbar:

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

Dette definerer en anonym funksjon som returnerer personens fulle navn når PersonViewModel.fullName er tilgjengelig. Dynamisk generering av hele navnet fra eksisterende komponenter (fornavn og etternavn) forhindrer oss i å lagre overflødige data, men det er bare halvparten av kampen. Vi må overføre denne funksjonen til ko.computed () for å opprette en beregningsbar observerbar. Dette forteller Knockout.js at den trenger å oppdatere noen HTML-elementer som er bundet til fullName-eiendommen når enten fornavn eller etternavnskifte.

La oss sørge for at vår beregne observerbare fungerer ved å binde "John's Shopping Cart" -linjen til fullt navn i stedet for fornavn:

 

's handlekurv

Nå skal siden din lese "John Smiths handlekurv." Deretter må vi sørge for at Knockout.js holder dette HTML-elementet synkronisert når vi endrer en av de underliggende egenskapene. Etter bindende en forekomst av PersonViewModel, prøv å endre sin firstName-egenskap:

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

Dette bør endre linjen til "Mary Smiths handlekurv." Igjen, husk at lesing eller innstilling av observerbare data skal gjøres med funksjonssamtaler, ikke oppgaven (=) operatør.

Beregnede observerbare data gir mange av de samme fordelene som Knockout.js automatisk synkronisering av visningen. I stedet for å holde oversikt over hvilke egenskaper som er avhengige av andre deler av ViewModel, kan beregne observerbare data bygge opp applikasjonen din rundt atomegenskaper og delegere avhengighetssporing til Knockout.js.


Observable Arrays

Observable arrayer lar Knockout.js spore lister over elementer. Vi vil utforske dette ved å opprette en side for handlekurv for brukeren vår. Først må vi opprette et egendefinert objekt for å representere produkter. På toppen av skriptet vårt, før du definerer PersonViewModel, legg til følgende objektdefinisjon:

 funksjon Produkt (navn, pris) this.name = ko.observable (navn); this.price = ko.observable (pris); 

Dette er bare et enkelt dataobjekt for å lagre noen få egenskaper. Vær oppmerksom på at det er mulig å gi observerbare egenskaper til flere objekter, og Knockout.js vil håndtere alle interdependensene i seg selv. Det er med andre ord mulig å skape forhold mellom flere ViewModels i et enkelt program.

Deretter skal vi lage noen få eksempler på vårt nye Produkt klassen og legg dem til brukerens virtuelle handlekurv. Inni PersonViewModel, definer en ny observerbar eiendom kalt shoppingCart:

 this.shoppingCart = ko.observableArray ([nytt produkt ("øl", 10.99), nytt produkt ("Brats", 7,99), nytt produkt ("boller", 1,49)]);

Dette er et innfødt JavaScript-utvalg som inneholder tre produkter pakket inn i et observerbart array slik at Knockout.js kan spore når elementer blir lagt til og fjernet. Men før vi begynner å manipulere objektene, la oss oppdatere vårt syn slik at vi kan se innholdet i handlevogn eiendom. Under

tag, legg til følgende:

 
Produkt Pris

Dette er en typisk HTML 5-tabell som inneholder en kolonne for produktnavn og en annen for produktpriser. Dette eksempelet introduserer også en ny binding kalt for hver. Når Knockout.js møter Foreach: ShoppingCart, Det løper gjennom hvert element i ViewModels handlevogn eiendom. Eventuelle markeringer inne i sløyfen evalueres i sammenheng med hvert element, så tekst: navnet refererer faktisk til shoppingCart [i] .name. Resultatet er en tabell med varer sammen med sine priser:

Figur 14: Skjermbilde av gjengitt produktoppføring

Detaljer om for hver bindende er utenfor omfanget av denne leksjonen. Den neste leksjonen gir en grundig diskusjon om foreach, og det introduserer også Knockout.js 'andre styringsflytbindinger. For nå, la oss komme tilbake til observerbare arrayer.

Legge til elementer

Hele poenget med å bruke observerbare arrayer er å la Knockout.js synkronisere visningen når vi legger til eller fjerner elementer. For eksempel kan vi definere en metode på vår ViewModel som legger til et nytt element, slik som:

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

Deretter kan vi opprette en knapp for å ringe metoden slik at vi kan legge til elementer på kjøretid og se Knockout.js holde listen oppdatert. Ved siden av kasseknappen i visningskoden legger du til følgende:

 

Når du klikker denne knappen, er ViewModels addProduct () Metoden utføres. Og siden handlevogn er et observerbart utvalg, legger Knockout.js inn en annen element for å vise det nye elementet. Å la Knockout.js holde oversikt over listeposter som dette, er mye mindre feilaktig enn å prøve å manuelt oppdatere

når vi endrer den underliggende matrisen.

Det er også verdt å påpeke at Knockout.js alltid gjør minimal mengden endringer som er nødvendige for å synkronisere brukergrensesnittet. I stedet for å regenerere hele listen hver gang et element er lagt til eller fjernet, sporer Knockout.js hvilke deler av DOM som er berørt og oppdateringer bare disse elementene. Denne innebygde optimaliseringen gjør det mulig å skala opp søknaden din til hundrevis eller til og med tusenvis av gjenstander uten å ofre responsivitet.

Slette elementer

På samme måte kan Knockout.js også slette elementer fra et observerbart array via fjerne() metode. Innsiden av PersonViewModel-definisjonen, legg til en annen metode for å fjerne elementer:

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

Deretter legger du til en sletteknapp for hvert element i

løkke:

 

Fordi vi er i for hver kontekst, vi måtte bruke $ root referanse til tilgang til vår ViewModel i stedet for gjeldende element i løkken. Hvis vi prøvde å ringe removeProduct () uten denne referansen, ville Knockout.js ha forsøkt å ringe metoden på produktklassen, som ikke eksisterer. Alle tilgjengelige bindende sammenhenger for foreach er dekket i neste leksjon.

Det faktum at vi er i en for hver loop slår også opp dette referanse i removeProduct (), så klikk på Fjerne knappen vil faktisk kaste en TypeError. Vi kan bruke et vanlig JavaScript-trick for å løse slike problemer. Øverst på PersonViewModel-definisjonen, tilordne dette til en ny variabel som heter selv:

 funksjon PersonViewModel () var selv = dette; ... 

Bruk deretter selv- i stedet for dette i methoden removeProduct ():

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

Du bør nå kunne manipulere vårt observerbare utvalg med Legg til øl og Fjerne knapper. Vær også oppmerksom på at Knockout.js automatisk legger til det nåværende elementet i løkken som den første parameteren til removeProduct ().

Ødelegge gjenstander

De fjerne() Metoden er nyttig for sanntids manipulering av lister, men det kan vise seg vanskelig når du begynner å prøve å sende data fra ViewModel til et server-side script.

For eksempel, vurder oppgaven med å lagre handlekurven i en database hver gang brukeren lagt til eller slettet et element. Med fjerne(), varen er fjernet umiddelbart, så alt du kan gjøre er å sende serveren din den nye listen i sin helhet - det er umulig å avgjøre hvilke elementer der det er lagt til eller fjernet. Du må enten lagre hele listen eller manuelt finne ut forskjellen mellom den forrige versjonen lagret i databasen og den nye som ble sendt inn fra AJAX-forespørselen.

Ingen av disse alternativene er spesielt effektiv, spesielt med tanke på Knockout.js vet nøyaktig hvilke elementer som ble fjernet. For å rette opp denne situasjonen inkluderer observerbare arrayer a ødelegge() metode. Prøv å endre PersonViewModel.removeProduct () til følgende:

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

Nå når du klikker på Fjerne knapp, Knockout.js vil ikke fjern elementet fra den underliggende gruppen. Dette vises i varselmeldingen, som skal ikke reduseres når du klikker på "Fjern". I stedet for å endre listen, ødelegge() metode legger til a _ødelegge eiendom til produktet og setter det til sant. Du kan vise denne egenskapen ved å legge til en annen varselmelding:

 alert (product._destroy);

De _ødelegge Egenskapen gjør det mulig å sortere gjennom en observerbar liste og trekke ut kun elementer som er slettet. Deretter kan du sende bare disse elementene til et server-side script for å bli slettet. Dette er en mye mer effektiv måte å håndtere lister når du arbeider med AJAX-forespørsler.

Legg merke til at for hver loop er klar over denne konvensjonen, og fjerner fortsatt de tilknyttede

element fra visningen, selv om elementet forblir i den underliggende gruppen.

Andre Array Methods

Internt observerbare arrayer er akkurat som normale observerbare egenskaper, bortsett fra at de støttes av et innfødt JavaScript-array i stedet for en streng, et nummer eller et objekt. Som vanlig observerbarhet, kan du få tilgang til den underliggende verdien ved å ringe det observerbare systemet uten noen egenskaper:

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

Å ringe denne metoden vil sløyfe gjennom den opprinnelige listens elementer, og den gir også tilgang til de innfødte JavaScript-array-metodene som trykk(), pop (), skift (), sorter (), osv.

Imidlertid definerer Knockout.js Dens eget versjoner av disse metodene på det observerbare arrayobjektet. For eksempel tidligere i denne leksjonen brukte vi shoppingCart.push () å legge til et element i stedet for handlekurv (). skyv (). Den tidligere kaller Knockout.js 'versjon, og sistnevnte kaller push () på det native JavaScript-systemet.

Det er vanligvis en mye bedre ide å bruke Knockout.js 'array metoder i stedet for å få tilgang til den underliggende arrayen direkte fordi det tillater Knockout.js å ​​automatisk oppdatere eventuelle avhengige visningskomponenter. Den komplette listen over observerbare array-metoder som tilbys av Knockout.js følger. De fleste av disse handler akkurat som deres innfødte JavaScript-kolleger.

  • trykk()
  • pop()
  • avskifte()
  • skifte()
  • skjære()
  • fjerne()
  • Fjern alle()
  • ødelegge()
  • destroyAll()
  • sortere()
  • reversert()
  • oversikt over()

Sammendrag

I denne leksjonen så vi hvordan beregnede observerbare data kan brukes til å kombinere normale observerbare objekter i sammensatte egenskaper som Knockout.js kan spore. Vi har også jobbet med observerbare arrayer, som er en måte for Knockout.js å ​​synkronisere lister over data i ViewModel med HTML-komponenter.

Sammen gir atom-, beregnede og array observables alle de underliggende datatyper du noensinne trenger for et typisk brukergrensesnitt. Beregnede observerbare observasjoner og observerbare arrayer gjør Knockout.js til et godt alternativ for rask prototyping. De lar deg sette alle dine komplekse funksjoner på ett sted, og la Knockout.js ta vare på resten.

For eksempel ville det være trivielt å opprette en beregnet observerbar som beregner totalprisen på hvert element i handlevogn liste og viser den nederst på siden. Når du har opprettet den funksjonaliteten, kan du gjenbruke den hvor som helst du trenger totalprisen (for eksempel en AJAX-forespørsel) bare ved å få tilgang til en ViewModel-egenskap.

Den neste leksjonen introduserer kontroll-flyt bindinger. De for hver bindende som vi brukte i denne leksjonen er trolig det vanligste kontrollflytverktøyet, men Knockout.js inneholder også noen få bindinger for finkornet kontroll over våre HTML-visningskomponenter.

Denne leksjonen representerer et kapittel fra Knockout Succinctly, en gratis eBok fra teamet på Syncfusion.