Bine ați venit în partea a doua a acestui tutorial; în prima parte am analizat câteva dintre elementele de bază ale modelului, colecției și vizualizării pentru lucrul cu Backbone și am văzut cum să afișăm vizualizările individuale de contact folosind o vizualizare master legată de o colecție.
În această parte a tutorialului, vom examina modul în care putem filtra viziunea noastră bazată pe datele introduse de utilizatori și cum putem adăuga un router pentru a da aplicației de bază funcționalitatea adreselor URL.
Vom avea nevoie de fișierele sursă din prima parte, deoarece vom construi codul existent pentru această parte. Aș recomanda cu fermitate citirea părții unu dacă nu ați făcut-o deja.
Este posibil să fi observat în parte că fiecare dintre modelele noastre individuale are un tip numit atribuit care categorizează fiecare model pe baza faptului că se referă la un prieten, un membru al familiei colegului. Să adăugăm un element select în vizualizarea principală, care va permite utilizatorului să filtreze contactele bazate pe aceste tipuri.
Acum, putem codifica un meniu selectat în codul de bază HTML și adăugăm manual opțiuni pentru fiecare dintre diferitele tipuri. Dar aceasta nu ar fi o gândire foarte avansată; dacă adăugăm mai târziu un tip nou sau ștergem toate contactele unui anumit tip? Aplicația noastră nu are încă capacitatea de a adăuga sau de a elimina contactele (partea a treia a alertei spoiler!), Dar este încă mai bine să luăm în considerare aceste tipuri de lucruri chiar și în acest stadiu incipient al aplicației noastre.
Ca atare, putem construi cu ușurință un element selectat dinamic pe baza tipurilor existente. Vom adăuga mai întâi un mic fragment HTML la pagina de bază; adăugați următoarele elemente noi în containerul de contacte:
Asta e, avem un exterior element pentru a acționa ca un container general, în cadrul căruia este un alt container cu un
id
atributul și a cu un text explicativ.
Acum să construim element. Mai întâi vom adăuga două metode noi pentru noi
DirectoryView
vizualizare maternă; primul va extrage fiecare tip unic și cel de-al doilea va construi drop-down-ul. Ambele metode ar trebui adăugate la sfârșitul vizualizării:
getTypes: function () returnați _.uniq (this.collection.pluck ("type"), false, funcția (type) return type.toLowerCase ();); , createSelect: funcția () var filter = this.el.find ("# filter"), select = $ ("", html:""); _.each (this.getTypes (), funcția (element) var opțiune = $ ("", value: item.toLowerCase (), text: item.toLowerCase ()); appendTo (select););
Prima metodă, getTypes ()
returnează un tablou creat folosind submeniul Underscore Uniq ()
metodă. Această metodă acceptă o matrice ca argument și returnează o nouă matrice care conține numai elemente unice. Matricea pe care o parcurgem Uniq ()
metoda este generată folosind Backbone's smulge ()
, care este o modalitate simplă de a trage toate valorile unui singur atribut dintr-o colecție de modele. Atributul care ne interesează aici este tip
atribut.
Pentru a preveni mai târziu problemele de caz, ar trebui de asemenea să normalizăm tipurile la litere mici. Putem folosi o funcție de iterator, furnizată ca al treilea argument Uniq ()
, pentru a transforma fiecare valoare înainte de a fi trecut prin comparator. Funcția primește elementul curent ca argument, așa că returăm elementul în format mic. Al doilea argument a fost transmis Uniq ()
, la care am stabilit fals
aici, este un steag utilizat pentru a indica dacă matricea care este comparată a fost sortată.
A doua metodă, createSelect ()
este puțin mai mare, dar nu este mult mai complexă. Singurul său scop este să creeze și să returneze un nou element, astfel încât să putem numi această metodă din altă parte a codului nostru și să primim o nouă casetă drop-down lucioasă, cu o opțiune pentru fiecare dintre tipurile noastre. Începem prin a da noii
Apoi folosim Underscore's fiecare()
metodă pentru a itera peste fiecare valoare din matricea returnată de către nostru getTypes ()
metodă. Pentru fiecare element din matrice creăm un nou element, setați textul la valoarea elementului curent (cu majuscule) și apoi adăugați-l la elementul curent
.
Pentru a face efectiv element pentru pagină, putem adăuga un cod în vizualizarea noastră principală
inițializa ()
metodă:
acest $ el.find ( "# filtru") adăuga (this.createSelect ())..;
Containerul pentru vizualizarea noastră principală este stocat în memoria cache $ el
proprietatea pe care Backbone o adaugă automat clasei noastre de vizualizare, așa că folosim acest lucru pentru a găsi containerul de filtru și a adăuga
Dacă conducem pagina acum, ar trebui să ne vedem noi element, cu o opțiune pentru fiecare dintre diferitele tipuri de contact:
Deci, acum avem noi
evenimente: "schimbare #filter select": "setFilter",
evenimente
atributul acceptă un obiect de valoare cheie
perechi unde fiecare cheie specifică tipul de eveniment și un selector pentru a lega dispozitivul de gestionare a evenimentelor. În acest caz suntem interesați de Schimbare
eveniment care va fi concediat de către
Apoi putem adăuga noul handler:
setFilter: funcție (e) this.filterType = e.currentTarget.value; this.trigger ( "schimbare: filterType"); ,
Tot ce trebuie să facem în setFilter ()
funcția este setată o proprietate pe ecranul principal numit filterType
, pe care le-am setat la valoarea opțiunii care a fost selectată, care este disponibilă prin currentTarget
proprietatea obiectului evenimentului care este transmisă în mod automat operatorului nostru.
Odată ce proprietatea a fost adăugată sau actualizată, putem declanșa și un obicei Schimbare
eveniment pentru a folosi numele proprietății ca spațiu de nume. Ne vom uita la modul în care putem folosi acest eveniment personalizat în doar un moment, dar înainte de a face, putem adăuga funcția care va efectua efectiv filtrul; după setFilter ()
adăugați următorul cod:
filterByType: funcția () if (this.filterType === "toate") this.collection.reset (contacte); altceva this.collection.reset (contacte, silent: true); var filterType = this.filterType, filtrat = _.filter (aceasta.collection.models, function (item) return element.get ("type") toLowerCase () === filterType;); this.collection.reset (filtrat);
Mai întâi verificăm dacă vizualizarea principală este filterType
proprietatea este setată la toate
; dacă este, repopulăm pur și simplu colecția cu setul complet de modele, datele pentru care sunt stocate local pe site-ul nostru contacte
mulțime.
Dacă proprietatea nu este egală toate
, încă reinițializăm colecția pentru a obține toate contactele înapoi în colecție, ceea ce este necesar pentru a comuta între diferitele tipuri de persoane de contact, însă de data aceasta am setat tăcut
opțiunea pentru Adevărat
(veți vedea de ce acest lucru este necesar într-un moment), astfel încât restabili
evenimentul nu este concediat.
Apoi stocăm o versiune locală a vizualizării filterType
proprietate, astfel încât să putem face referință în cadrul unei funcții de apel invers. Folosim Underscore's filtru()
pentru filtrarea colecției de modele. filtru()
metoda acceptă matricea să filtreze și o funcție de apel invers să fie executată pentru fiecare element din matricea care este filtrată. Funcția de retur este transmisă elementului curent ca argument.
Funcția de apel invers va reveni Adevărat
pentru fiecare element care are a tip
atribut egal cu valoarea pe care tocmai am stocat-o în variabilă. Tipurile sunt din nou convertite în litere mici, din același motiv ca înainte. Orice elemente care revin la funcția de apel invers fals
pentru că sunt eliminate din matrice.
Odată ce matricea a fost filtrată, sunăm reset ()
din nou, trecând în matricea filtrată. Acum suntem pregătiți să adăugăm codul care va face conexiunea settype ()
metodă, filterType
proprietate și filterByType ()
metodă.
La fel ca și evenimentele UI obligatorii pentru interfața noastră folosind evenimente
atribut, putem, de asemenea, să le angajăm pe colectorii de evenimente. În a noastră setFilter ()
metoda pe care am tras un eveniment personalizat, acum trebuie să adăugăm codul care va lega filterByType ()
la acest eveniment; adăugați următorul cod la inițializa ()
metoda vederii noastre principale:
this.on ("schimbare: filterType", this.filterByType, this);
Folosim Backbone's pe()
pentru a asculta pentru evenimentul nostru personalizat. Specificăm filterByType ()
metoda ca funcție de manipulare pentru acest eveniment utilizând al doilea argument al lui pe()
, și poate seta și contextul pentru funcția de apel invers prin setare acest
ca al treilea argument. acest
Obiectul aici se referă la vederile noastre principale.
În a noastră filterByType
, reinițializăm colecția pentru ao repopula fie cu toate modelele, fie cu modelele filtrate. De asemenea, ne putem lega de restabili
pentru a repopula colecția cu instanțe de model. Putem specifica o funcție de manipulare și pentru acest eveniment, iar lucrul grozav este că deja avem funcția. Adăugați următoarea linie de cod direct după Schimbare
legarea evenimentului:
this.collection.on ("resetare", acest.render, acest lucru);
În acest caz, ascultăm pentru restabili
eveniment și funcția pe care dorim să o invocăm este cea a colecției face()
metodă. De asemenea, specificăm că apelul trebuie utilizat acest
(ca în cazul vederii principale) ca context în care este executat. Dacă nu furnizăm acest
ca al treilea argument, nu vom putea accesa colecția din interiorul face()
atunci când se ocupă de restabili
eveniment.
În acest moment, acum ar trebui să constatăm că putem folosi caseta de selectare pentru a afișa subseturile contactelor noastre. Motivul pentru care am setat tăcut
opțiune la adevărat în nostru filterByType ()
metoda este astfel încât vederea să nu fie redată în mod inutil când resetăm colecția la începutul celei de-a doua ramuri a condiționării. Trebuie să facem acest lucru astfel încât să putem filtra un singur tip și apoi să filtram un alt tip fără a pierde niciun model.
Deci, ceea ce am ajuns până acum este în regulă, putem filtra modelele noastre utilizând caseta de selectare. Dar nu ar fi minunat dacă am putea filtra colecția folosind și un URL? Modulul de router al modulului Backbone ne oferă această abilitate, să vedem cum, și din cauza modului frumos decuplat pe care l-am structurat până acum în filtrarea noastră, este de fapt foarte ușor să adăugați această funcție. Mai întâi trebuie să extindem modulul Router; adăugați următorul cod după vizualizarea principală:
var ContacteRouter = Backbone.Router.extend (trase: "filter /: type": "urlFilter", urlFilter: function (type) directory.filterType = type; directory.trigger ("change: filterType" );
Prima proprietate pe care o definim în obiectul transmis către Router extinde()
metoda este rute
, care ar trebui să fie un obiect literal în care fiecare cheie este o adresă URL care să se potrivească, iar fiecare valoare este o funcție de apel invers atunci când adresa URL este potrivită. În acest caz, căutăm adrese URL care încep cu #filtru
și se termină cu orice altceva. Partea din URL după filtru/
o parte este trecută la funcția pe care o specificăm ca fiind funcția de apel invers.
În cadrul acestei funcții, setăm sau actualizăm filterType
proprietatea vederii principale și apoi declanșarea obiceiului nostru Schimbare
eveniment din nou. Acesta este tot ce trebuie să facem pentru a adăuga funcționalitatea de filtrare utilizând adresa URL. Totuși, trebuie să creăm o instanță a routerului nostru, pe care o putem face adăugând următoarea linie de cod direct după DirectoryView
instanțierea:
var contactsRouter = nou ContacteRouter ();
Ar trebui să introducem acum o adresă URL, cum ar fi # Filtru / familie
iar punctul de vedere se va reda în sine pentru a arăta doar contactele cu familia de tip:
Deci asta e destul de bine? Dar există încă o parte lipsă - cum vor ști utilizatorii să utilizeze URL-urile noastre frumoase? Trebuie să actualizăm funcția care gestionează evenimentele UI pe
Pentru a face acest lucru este nevoie de doi pași; în primul rând ar trebui să permitem suportul istoric al Backbone pornind serviciul de istorie după ce aplicația noastră a fost inițializată; adăugați următoarea linie de cod chiar la sfârșitul fișierului nostru script (imediat după inițierea routerului):
Backbone.history.start ();
Din acest moment, Backbone va monitoriza adresa URL pentru modificările hash. Acum, când vrem să actualizăm adresa URL după ce se întâmplă ceva, sunăm doar navigare ()
metoda routerului nostru. Schimba filterByType ()
astfel încât să apară astfel:
filterByType: funcția () if (this.filterType === "toate") this.collection.reset (contacte); contactsRouter.navigate ( "filtru / all"); altceva this.collection.reset (contacte, silent: true); var filterType = this.filterType, filtrat = _.filter (this.collection.models, function (item) return element.get ("type") === filterType;); this.collection.reset (filtrat); contacteRouter.navigate ("filter /" + filterType);
Acum, când caseta de selecție este utilizată pentru filtrarea colecției, adresa URL va fi actualizată, iar utilizatorul poate să marcheze sau să partajeze adresa URL, iar butoanele din spate și înainte din browser vor naviga între state. Deoarece versiunea 0.5 Backbone a acceptat de asemenea API-ul pushState, cu toate acestea, pentru ca aceasta să funcționeze corect, serverul trebuie să poată afișa paginile solicitate, pe care nu le-am configurat pentru acest exemplu, folosind modulul istoric standard.
În această parte a tutorialului, am analizat mai multe module Backbone, în special modulele Router, History and Events. Am analizat acum toate modulele care vin cu Backbone.
De asemenea, ne-am uitat la alte metode de subversiune, inclusiv filtru()
, pe care am folosit-o pentru a filtra colecția noastră numai pentru acele modele care conțin un tip specific.
În cele din urmă, ne-am uitat la modulul Router din Backbone, care ne-a permis să setăm rute care pot fi potrivite de aplicația noastră pentru a declanșa metode și modulul Istoric pe care îl putem folosi pentru a ne aminti de stat și pentru a păstra adresa URL actualizată cu fragmente de hash.
Un punct de luat în considerare este natura cuplată în mod liber a funcționalității noastre de filtrare; cand am adaugat filtrarea prin meniul selectat, a fost facut in asa fel incat a fost foarte rapid si usor sa vina dupa aceea si sa adaugam o metoda noua de filtrare fara a fi nevoie sa ne schimbam filtru()
metodă. Aceasta este una dintre cheile pentru a construi cu succes aplicații non-banale, care pot fi întreținute și scalabile. Dacă vrem, ar fi foarte ușor să adăugăm o altă metodă complet nouă de filtrare, care trebuie să schimbe metoda de filtrare.
În următoarea parte a acestei serii, vom reveni la lucrul cu modelele și vom vedea cum putem elimina modelele și le vom adăuga pe cele noi în colecție.