Construiți un manager de contacte utilizând Backbone.js Partea 2

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.


Reacționarea la intrarea utilizatorului

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 ", html:""); _.each (this.getTypes (), funcția (element) var opțiune = $ ("

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 .

Pentru a face efectiv element, cu o opțiune pentru fiecare dintre diferitele tipuri de contact:


Filtrarea vederii

Deci, acum avem noi , putem adăuga funcția de filtrare a vederii când este selectată o opțiune. Pentru a face acest lucru, putem folosi vizualizarea master evenimente atribut pentru a adăuga un manipulator de eveniment UI. Adăugați următorul cod direct de la noi renderSelect () metodă:

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 element în cadrul #filtru container. Fiecare valoare din obiect este manipulatorul evenimentului care trebuie legat; în acest caz specificăm setFilter ca manipulant.

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ă.


Evenimente obligatorii la Colecție

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.


Routing

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 astfel încât adresa URL să fie actualizată când se utilizează caseta de selectare.

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.


rezumat

Î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.

Cod