Knockout Observatori

Am văzut cum proprietățile observabile l-au lăsat pe Knockout.js să actualizeze automat elementele HTML atunci când se schimbă datele, dar acesta este doar începutul utilității lor. Knockout.js vine, de asemenea, cu două modalități suplimentare de a expune proprietățile ViewModel: observabile calculate și matrice observabile. Împreună, acestea deschid o lume complet nouă de posibilități pentru interfețele utilizatorilor bazate pe date.

Observabile computerizate să vă creați proprietăți generate dinamic. Aceasta înseamnă că puteți combina mai multe observații obișnuite într-o singură proprietate și Knockout.js va păstra în continuare actualizarea ori de câte ori se modifică oricare dintre valorile de bază.

Figura 12: O observabilă calculată depinde de două observabile normale

Tablouri observabile combinați puterea observabilelor lui Knockout.js cu matricele JavaScript native. Ca array-uri native, ele conțin liste de elemente pe care le puteți manipula. Dar, deoarece sunt observabile, Knockout.js actualizează automat toate elementele asociate HTML ori de câte ori elementele sunt adăugate sau eliminate.

Figura 13: O matrice observabilă care conține alte modele ViewModels

Abilitatea de a combina observabilele, împreună cu abilitatea de a lucra cu liste de articole, oferă toate structurile de date de care aveți nevoie într-un ViewModel. Această lecție introduce ambele subiecte cu o simplă interfață de coș de cumpărături.


Conformitate observabile

În primul rând, vom începe cu o simplă observabilă calculată. Dedesubt Nume și numele de familie observabile în PersonViewModel, creați observabilul calculat fullName:

 this.fullName = ko.computed (funcția () return this.firstName () + "" + this.lastName ();, aceasta);

Aceasta definește o funcție anonimă care întoarce oricând numele complet al persoanei PersonViewModel.fullName este accesat. Dinamic generând numele complet din componentele existente (Nume și lastName) ne împiedică să stocăm date redundante, dar asta e doar jumătatea bătăliei. Trebuie să trecem această funcție la ko.computed () pentru a crea o observabilă calculată. Acest lucru îi spune Knockout.js că trebuie să actualizeze toate elementele HTML legate de proprietatea fullName ori de câte ori se schimba numele FirstName sau LastName.

Să ne asigurăm că lucrările noastre observabile calculate prin legarea liniei "John's Shopping Cart" Numele complet în loc de firstName:

 

Cosul de cumparaturi

Acum, pagina dvs. ar trebui să citească "Coșul de cumpărături al lui John Smith". Apoi, asigurați-vă că Knockout.js păstrează acest element HTML sincronizat când schimbăm una dintre proprietățile de bază. După ce a legat o instanță de PersonViewModel, încercați să schimbați proprietatea firstName:

 var vm = nou PersonViewModel (); ko.applyBindings (vm); vm.firstName ( "Maria");

Aceasta ar trebui să schimbe linia către "Cosul de cumpărături al lui Mary Smith". Din nou, rețineți că citirea sau setarea observabilelor ar trebui să se facă cu apeluri de funcții, nu cu misiunea (=) operator.

Observatoarele computerizate oferă multe din aceleași avantaje ca sincronizarea automată a vizualizării de către Knockout.js. În locul faptului că trebuie să țineți evidența proprietăților care se bazează pe alte părți ale modelului ViewModel, observabilele calculate vă permit să vă construiți aplicația în jurul proprietăților atomice și să delegați urmărirea dependenței la Knockout.js.


Maneuri observabile

Tabelele de alertă percepute permit Knockout.js să urmărească listele de elemente. Vom explora acest lucru prin crearea unei pagini de afișare a coșului de cumpărături pentru utilizatorul nostru. În primul rând, trebuie să creați un obiect personalizat pentru a reprezenta produsele. În partea de sus a scenariului nostru, înainte de a defini PersonViewModel, adăugați următoarea definiție a obiectului:

 funcția Produs (nume, preț) this.name = ko.observable (nume); this.price = ko.observable (preț); 

Acesta este doar un obiect de date simplu pentru stocarea câtorva proprietăți. Rețineți că este posibil să se acorde mai multe obiecte obiecte observabile și Knockout.js va gestiona toate interdependențele pe cont propriu. Cu alte cuvinte, este posibil să se creeze relații între multiplu ViewModels într-o singură aplicație.

Apoi, vom crea câteva exemple ale noului nostru model Produs clasă și adăugați-le în coșul de cumpărături virtual al utilizatorului. Interior de PersonViewModel, defini o nouă proprietate observabilă numită shoppingCart:

 this.shoppingCart = ko.observableArray (nou produs ("Beer", 10.99), nou produs ("Brats", 7.99), nou produs ("Buns", 1.49)]);

Aceasta este o matrice JavaScript nativă care conține trei produse înfășurate într-o matrice observabilă, astfel încât Knockout.js poate urmări când articolele sunt adăugate și eliminate. Dar, înainte de a începe manipularea obiectelor, să ne actualizăm viziunea pentru a putea vedea conținutul cărucior de cumpărături proprietate. Dedesubt

tag, adăugați următoarele:

 
Produs Preț

Acesta este un tabel tipic HTML 5 care conține o coloană pentru numele produselor și un altul pentru prețurile produselor. Acest exemplu introduce, de asemenea, o nouă legare numită pentru fiecare. Când se întâlnesc Knockout.js foreach: shoppingCart, acesta trece prin fiecare element din ViewModel cărucior de cumpărături proprietate. Orice marcaj din interiorul buclă este evaluat în contextul fiecărui element, astfel încât textul: numele se referă de fapt la shoppingCart [i] .name. Rezultatul este un tabel de elemente alături de prețurile lor:

Figura 14: Captură de ecran a listei de produse redate

Detaliile pentru fiecare obligatorii sunt în afara scopului acestei lecții. Următoarea lecție oferă o discuție aprofundată a foreach-ului și introduce, de asemenea, legăturile de control al fluxului de control al lui Knockout.js. Pentru moment, să ne întoarcem la mese observabile.

Adăugarea de elemente

Întregul punct de utilizare a rețelelor observabile este să lăsăm Knockout.js să sincronizeze vizualizarea ori de câte ori adăugăm sau eliminăm elemente. De exemplu, putem defini o metodă pe ViewModel care adaugă un element nou, cum ar fi:

 this.addProduct = function () this.shoppingCart.push (nou produs ("Mai multe bere", 10.99)); ;

Apoi, putem crea un buton pentru a apela metoda, astfel încât să putem adăuga elemente la timpul de execuție și să vedem că Knockout.js păstrează lista actualizată. În dreptul butonului de verificare din codul de vizualizare, adăugați următoarele:

 

Când faceți clic pe acest buton, vizualizați modelul addProduct () metoda este executată. Și, din moment ce cărucior de cumpărături este o matrice observabilă, Knockout.js inserează un altul element pentru a afișa elementul nou. Permiteți Knockout.js să urmăriți elementele listate, cum ar fi acest lucru, este mult mai puțin predispusă la erori decât încercarea de a actualiza manual

ori de câte ori schimbăm matricea de bază.

De asemenea, merită să subliniem faptul că Knockout.js întotdeauna face minim numărul de modificări necesare pentru sincronizarea interfeței cu utilizatorul. În loc să regenerați întreaga listă de fiecare dată când un element este adăugat sau eliminat, Knockout.js urmărește care părți ale DOM sunt afectate și actualizări numai aceste elemente. Această optimizare încorporată face posibilă extinderea aplicației dvs. la sute sau chiar mii de articole fără a sacrifica reacția.

Ștergerea elementelor

În mod similar, Knockout.js poate șterge, de asemenea, elemente dintr - o matrice observabilă prin elimina() metodă. În interiorul definiției PersonViewModel, adăugați o altă metodă de eliminare a elementelor:

 this.removeProduct = funcție (produs) this.shoppingCart.remove (produs); ;

Apoi, adăugați un buton de ștergere pentru fiecare element din

buclă:

 

Pentru că suntem în pentru fiecare context, trebuia să folosim $ rădăcină referință pentru accesarea ViewModelului nostru în locul elementului curent din buclă. Dacă am încercat să sunăm removeProduct () fără această referință, Knockout.js ar fi încercat să apeleze metoda din clasa Product, care nu există. Toate contextele legale disponibile pentru foreach sunt acoperite în următoarea lecție.

Faptul că suntem într-un pentru fiecare buclă, de asemenea, încurcă acest referință în removeProduct (), făcând clic pe a Elimina butonul va arunca de fapt un TypeError. Putem folosi un truc comun JavaScript pentru a rezolva aceste tipuri de probleme de domeniu. În partea de sus a definiției PersonViewModel, atribuiți aceasta unei noi variabile numite auto:

 funcția PersonViewModel () var self = aceasta; ... 

Apoi, utilizați de sine in loc de acest în metoda removeProduct ():

 this.removeProduct = funcție (produs) self.shoppingCart.remove (produs); ;

Acum ar trebui să puteți manipula matricea noastră observabilă cu Adaugă Beer și Elimina butoane. De asemenea, rețineți că Knockout.js adaugă automat elementul curent în buclă ca primul parametru removeProduct ().

Distrugerea obiectelor

elimina() este utilă pentru manipularea în timp real a listelor, dar se poate dovedi dificilă odată ce începeți să încercați să trimiteți date din ViewModel către un script de server.

De exemplu, luați în considerare sarcina de a salva coșul de cumpărături într-o bază de date de fiecare dată când utilizatorul a adăugat sau a șters un articol. Cu elimina(), elementul este eliminat imediat, astfel încât tot ce puteți face este să trimiteți serverului noua listă în întregime - este imposibil să determinați ce elemente au fost adăugate sau eliminate. Trebuie fie să salvați întreaga listă, fie să înțelegeți manual diferența dintre versiunea anterioară stocată în baza de date și cea nouă transmisă din cererea AJAX.

Nici una dintre aceste opțiuni nu este deosebit de eficientă, mai ales dacă Knockout.js știe exact ce articole au fost eliminate. Pentru a remedia această situație, matricele observabile includ a distruge() metodă. Încercați să schimbați PersonViewModel.removeProduct () la următoarele:

 this.removeProduct = funcție (produs) self.shoppingCart.destroy (produs); alert (self.shoppingCart () lungime.); ;

Acum când faceți clic pe Elimina buton, Knockout.js nu va eliminați elementul din matricea de bază. Acest lucru este afișat în mesajul de alertă, care ar trebui să fie nu scade când faceți clic pe "Eliminați". În loc să modificați lista, faceți clic pe distruge() metoda adaugă a _distruge proprietatea asupra produsului și îl stabilește la adevărat. Puteți afișa această proprietate adăugând un alt mesaj de alertă:

 alert (product._destroy);

_distruge proprietatea face posibilă sortarea printr-o listă observabilă și extragerea numai a elementelor care au fost șterse. Apoi, puteți să trimiteți numai acele elemente la un script de pe server să fie șterse. Aceasta este o modalitate mult mai eficientă de gestionare a listelor atunci când lucrați cu cereri AJAX.

Rețineți că pentru fiecare buclă este conștient de această convenție, și înlătură încă asociate

element din vizualizare, chiar dacă elementul rămâne în matricea de bază.

Alte metode array

Pe plan intern, matricele observabile sunt la fel ca proprietățile obișnuite observabile, cu excepția faptului că sunt susținute de o matrice JavaScript nativă în loc de un șir, de un număr sau de un obiect. Ca observabile obișnuite, puteți accesa valoarea de bază prin apelarea matricei observabile fără proprietăți:

 this.debugItems = funcția () var message = ""; var nativeArray = această coș de cumpărături (); pentru (var i = 0; i 

Apelarea acestei metode se va realiza prin intermediul elementelor din lista nativă și va oferi, de asemenea, acces la metodele native ale JavaScript Apăsați(), pop (), shift (), sort (), etc.

Cu toate acestea, Knockout.js definește propria versiuni ale acestor metode pe obiectul observabil al matricei. De exemplu, mai devreme în această lecție, am folosit shoppingCart.push () pentru a adăuga un element în loc de ShoppingCart (). împinge (). Fosta numește versiunea Knockout.js, iar cea din urmă numește push () pe matricea JavaScript nativă.

Este de obicei o idee mult mai bună de a utiliza metode de array ale lui Knockout.js în loc de a accesa direct matricea de bază, deoarece permite Knockout.js să actualizeze automat toate componentele de vizualizare dependente. Apare lista completă a metodelor observabile de matrice furnizate de Knockout.js. Cele mai multe dintre acestea acționează exact ca și omologii lor nativi JavaScript.

  • Apăsați()
  • pop()
  • unshift()
  • schimb()
  • felie()
  • elimina()
  • inlătură tot()
  • distruge()
  • destroyAll()
  • fel()
  • inversat()
  • Index de()

rezumat

În această lecție, am văzut cum observabilele computerizate pot fi folosite pentru a combina observabilele normale în proprietățile compuse pe care le poate urmări Knockout.js. Am lucrat, de asemenea, cu matrice observabile, care sunt o modalitate pentru Knockout.js de a sincroniza liste de date în ViewModel cu componente HTML.

Împreună, observațiile atomice, computerizate și matricele furnizează toate tipurile de date care stau la baza pe care le veți avea vreodată pentru o interfață tipică de utilizator. Observatoarele compuse și matricele observabile fac Knockout.js o opțiune excelentă pentru prototipuri rapide. Ele vă permit să puneți toate funcționalitățile complexe într-un singur loc, apoi lăsați Knockout.js să aibă grijă de restul.

De exemplu, ar fi banal să creați o observabilă calculată care să calculeze prețul total al fiecărui element în cărucior de cumpărături afișați-o și afișează-o în partea de jos a paginii. Odată ce creați acea funcționalitate, o puteți reutiliza oriunde aveți nevoie de prețul total (de exemplu, o solicitare AJAX) doar accesând o proprietate ViewModel.

Următoarea lecție introduce legăturile de control-flow. pentru fiecare legarea pe care am folosit-o în această lecție este probabil cea mai obișnuită unealtă de control-flow, dar Knockout.js include și câteva legări suplimentare pentru controlul fin al elementelor de vizualizare HTML.

Această lecție reprezintă un capitol din Knockout Succinct, o carte electronică gratuită de la echipa de la Syncfusion.

Cod