Ca și în cazul oricărei aplicații web, crearea site-urilor cu mai multe pagini necesită un set specializat de instrumente. În acest articol, vom analiza dezvoltarea unei biblioteci care nu numai că poate diferenția diferitele URI-uri, ci una care profită de caracteristicile principale ale Meteor.
Ori de câte ori trebuie să dezvolte o bibliotecă specifică și concentrată ca aceasta, îmi place să încep cu rezultatul, cum vreau să funcționeze?
Deci, putem începe prin a scrie câteva dintre caracteristicile pe care le-am dori să aibă:
Arată destul de bine. Acum, după ce ați analizat aceste caracteristici, vă puteți gândi că sunt destul de asemănătoare cu tipul de bibliotecă "ruter" și sunt de acord. Deci, să aruncăm o privire la modul în care biblioteca noastră "ruter" ar funcționa în acțiune:
Router.addRoute ('/ home', 'homeTemplate'); Router.addRoute ('/ user /: username', 'profileTemplate'); Router.addRoute ('/ contact', 'contactTemplate'); Router.run ();
În design, aveți concepte precum "forma-urmează-funcția", care folosește ideea de a pune totul pe primul loc și de ao proiecta mai târziu.
În cod, adesea găsesc opusul este mai util. Noi, ca dezvoltatori, putem lucra în multe direcții și avem un exemplu de lucru cu privire la ceea ce ar trebui să arate designul, ne păstrează concentrarea și eficiența.
Acum că știu ce vreau să fac, este doar o chestiune de implementare. Deci, hai să aruncăm o privire mai departe la caracteristicile pe care le-am scris mai sus; dorim să putem adăuga trasee și Meteor să facă parțial șablonul dat. Desigur, vederile lui Meteor funcționează în mod prestabilit din șabloanele ghidonului, deci am luat decizia de a face acest lucru denominația routerului nostru.
Apoi, să descompunem proiectul în diferite secțiuni, astfel încât să știm la ce caracteristici trebuie să lucrăm.
window.location.pathname
variabilă, furnizată de browser.addRoute
care va accepta un model de traseu și un nume de șablon. Această funcție va trebui apoi să stocheze toate aceste obiecte de rute într-un fel de matrice.Din fericire, puteți observa că, prin stabilirea cerințelor, aceasta contribuie cu adevărat la eficientizarea etapei de planificare. Suntem gata să intrăm.
Pentru a începe, să creați un nou proiect Meteor, voi numi a mea "routerdemo
“. Acum, înăuntru, vom crea un dosar numit "lib
"într-un alt folder numit"client
„:
meteor creează routerdemo cd routerdemo mkdir -p client / lib
Apoi, creați un fișier numit "router.js
"în interiorul noului creat lib
pliant. Motivul pentru care îl lipim în "client
", se datorează faptului că serverul nu are acces la window.location.pathname
variabilă și, ca atare, nu va funcționa cu ruterul nostru. Punerea lucrurilor într-un folder numit "client
"asigură că acestea vor fi difuzate doar pe partea clientului.
Acum înăuntru router.js
dosar pe care tocmai l-ați făcut, să punem niște schele:
////////// // Router //////////// Router ///// Router = uri: / * Adresa URL curent * /, rute: [], addRoute: / * functie pentru a adauga un traseu * /, getMatchingRoute: / * pentru a afișa șablonul rutei potrivite * /;
Cred că eo schemă destul de bună, chiar am completat codul pentru matricea rutelor și am adăugat câteva comentarii (progres!). Acum, pentru a ne dezvolta în continuare biblioteca, trebuie să discutăm despre modul în care vom mula aceste rute împreună.
Acest lucru nu este la fel de simplu ca routeRoute ===
, deoarece avem de-a face cu înlocuitori dinamici. Vrem un traseu pentru "/numele de utilizator
'pentru a se potrivi cu un URI din'/ User / 42
' si asa mai departe.
Pentru a face acest lucru, va trebui să împărțim URI-ul și să facem o analiză mai detaliată. Acum, unii oameni s-ar putea gândi să folosească un regex, dar, este puțin peste vârf dacă mă întrebi. O abordare mult mai simplă ar fi divizarea segmentelor și asigurarea faptului că cele două rute au același număr de segmente și, de asemenea, se asigură că părțile rutei care nu sunt substituente se potrivesc.
Acest lucru poate fi realizat cu ușurință prin împărțirea URI unde există vreodată un slash ('/'), folosind .Despică
metodă. Prin urmare, prima noastră verificare ar asigura că cele două rute au același număr de segmente.
Dacă ruta este "/numele de utilizator
"și vom obține un URI de"/ Profil / 42 / foo / bar
", nici măcar nu trebuie să facem nici o verificare suplimentară, una are două segmente, iar cealaltă are patru, așa că pare o verificare primară. Următorul lucru pe care îl putem face este să filtrați listele și să vă asigurați că fiecare piesă care nu este un substituent se potrivește. Dacă aceste două verificări sunt adevărate, știm că se potrivește traseul.
Deci, să începem cu setarea uri
variabil:
uri: _.compact (window.location.pathname.split ("/")),
În codul de mai sus, împărțim matricea pe slash-urile din față și transformăm șirul într-o serie de segmente. Apoi folosim Underscore compact
pentru a elimina toate elementele goale din listă, acestea ar putea fi cauzate de un slash înainte la început sau de către cineva care folosește din greșeală două tăieturi din față. Făcând acest lucru, face sistemul nostru mult mai iertător.
Apoi, trebuie să creăm funcția de adăugare a unui traseu, acesta este un proces destul de similar, dar pentru că vom alimenta locurile de substituție mai târziu, vom stoca nu doar segmentele și numele șablonului, ci și indicii pentru și placeholderilor.
Iată funcția completă:
addRoute: funcție (rută, șablon) var segments = _.compact (route.split ("/")); var placeholders = _.reduce (segmente, funcție (currentArr, bucată, index) if (piece.substr (0, 1) === ":") currentArr.push (index); substr (1); retur curentArr;, []); this.routes.push (rută: segmente, șablon: șablon, placeholderIndexes: placeholders); ,
Începem prin împărțirea rutei în segmente, așa cum am făcut pentru URI, dar de data aceasta trebuie să stocăm și indiciile substituentului pentru referințe ulterioare, folosind submeniul Underscore reduce
metodă.
Pentru cei care nu știu, reduce
funcția este similară cu fiecare
metoda, ea cicluri, de asemenea, prin toate elementele unei liste, diferența fiind, ea trece orice indiferent de fiecare iterație revine la următorul element, returnând în cele din urmă rezultatele la variabila dată. Începem cu o matrice goală (al treilea parametru) și adăugăm fiecare index pe măsură ce îl găsim și trecând matricea până când, în cele din urmă, se întoarce înapoi la substituenţi
variabil.
Următorul lucru pe care îl veți vedea aici este că redenumim segmentele care sunt substituenți și eliminăm colonul. Facem acest lucru numai din motive estetice și, ulterior, va fi mai ușor de referință în șabloane.
În cele din urmă, împingem noile date pe ruta noastră, pe care am creat-o mai devreme.
Următorul pas este să filtrați lista și să căutați un traseu care să corespundă URI-ului curent.
Iată funcția completă:
getMatchingRoute: funcția () pentru (var i în this.routes) var route = this.routes [i]; var data = ; dacă (trase.segment.length === this.uri.length) var match = _.every (seg, i) if (_.contains (route.placeholderIndexes, i) [return] seg === this.uri [i];, aceasta); dacă se potrivesc retur date: date, șablon: route.template // nu există potriviri (adăugați 404 sau șablonul implicit poate?) return false; ,
Facem cateva lucruri aici, asa ca haideti sa mergem prin ea. Începem cu bicicleta prin intermediul gamei de rute și atribuim ruta curentă unei variabile, împreună cu un obiect de date gol pentru a stoca locurile de substituire.
Apoi, facem verificarea inițială pentru a ne asigura că cele două rute au același număr de segmente, altfel pur și simplu mergem pe următoarea rută. În cazul în care aceștia au același număr de componente, trebuie să verificăm dacă segmentele se potrivesc, acest lucru se poate face folosind submeniul "_.fiecare
". Această funcție este din nou ca "_.fiecare
", cu excepția faptului că returnează un boolean. Modul în care funcționează este că va rula funcția pentru fiecare element din matrice, dacă toate se vor întoarce la adevărat, funcția va reveni la adevărat, în caz contrar va reveni la falsă, deci este perfect pentru a face astfel de lucruri unde trebuie să verificăm fiecare segment.
Acum, verificarea performanței este destul de ușoară, dacă este un substituent, atunci se potrivește automat, deoarece un substituent poate fi egal cu orice valoare. Dacă nu este un substituent, ne asigurăm că cele două segmente se potrivesc, destul de simple.
Pentru a verifica dacă este sau nu un substituent, vom trece indexul de segmente curente (stocat în 'eu
') către Underscore's _.contains
care va verifica valoarea sa.
Acum s-ar putea să te întrebi ce înseamnă prima linie în interiorul acestui "dacă
"se face, bine, stocarea segmentului în matricea de date sub numele de înlocuitor dat. Deci, spuneți, de exemplu, ați avut un traseu de "/nume de utilizator
"iar URI curent este"/ User / bob
', atunci această linie va adăuga o proprietate la obiectul de date numit'Nume
"și să i se dea o valoare bob
.
Restul este destul de evident, trecem adevărat sau fals, în funcție de circumstanțe, iar rezultatul este stocat în "Meci
“. Dacă potrivirea este adevărată, vom returna datele împreună cu numele șabloanelor, iar dacă nu există nici o potrivire, returnăm false. Și asta e pentru noi getMatchingRoute
metodă.
Până acum, putem obține URI-ul curent, putem adăuga rute și putem găsi o rută de potrivire, singurul lucru rămas este să afișăm ruta corectă și pentru aceasta trebuie să scrieți "alerga
".
Meteor utilizează ghidon pentru șabloane și stochează toate șabloanele într-o variabilă, denumită în mod corespunzător "Format
“. Acum, dacă sunteți familiarizați cu ghidonul, atunci știi că aceste șabloane sunt doar funcții, și sunând-le (opțional trecând unele date) vom primi înapoi codul șablonului.
Acum, apelarea acestor funcții pentru a obține codul HTML al șablonului ar funcționa bine, dar nu este foarte asemănătoare cu Meteor, pentru că ceea ce am avea de-a face cu site-ul este doar un site static normal. Din fericire, adăugarea în comportamentul dinamic este mai ușoară decât ați putea crede, tot ceea ce trebuie să faceți este să înfășurați apelul funcției într-o "Meteor.render
' apel. Punerea în interiorul acestei funcții o va face să reacționeze la modificările date și să o țină "în direct".
Din acest motiv, rularea ruterului este foarte simplă, să creăm metoda de rulare:
rulați: funcția () var route = this.getMatchingRoute (); dacă (ruta) var fragment = Meteor.render (funcția () if (Șablon [route.template]! == undefined) retur Template [route.template] (calea dată); document.body.appendChild (fragment); altfel // 404
Începem prin a obține ruta potrivită, folosind getMatchingRoute
funcția pe care tocmai am scris-o, apoi ne asigurăm că există un meci și, în final, vom folosi un altfel
declarație pentru a manipula afișarea unui 404.
În cadrul instrucțiunii if, sunăm Meteor.render
și înăuntru, verificăm și sunăm șablonul returnat, trecând cu el datele de la locurile de substituție. Această funcție va returna un fragment HTML, pe care apoi îl putem adăuga la corpul documentului.
Cu aproximativ 60 de linii de cod, am finalizat ruterul nostru.
Următorul pas este să-l testați. Voi folosi același cod pe care l-am scris mai devreme când am planificat acest proiect, deoarece va fi o măsură bună dacă am realizat ceea ce am vrut să realizăm. Să adăugăm un fișier numit main.js
în interiorul client
și adăugați următoarele:
Meteor.startup (funcția () Router.addRoute ('/ home', 'homeTemplate'); Router.addRoute ('/ user /: username', 'profileTemplate' '); Router.run (););
În codul de mai sus, trebuie mai întâi să ne asigurăm că șabloanele și corpul nostru vor fi disponibile înainte de a încerca să lucrăm cu Router-ul nostru. Facem asta prin împachetarea întregului cod din interiorul Meteor.startup
apel de metodă. Acest lucru va asigura totul este gata, și în interiorul lansare
, putem adăuga rutele noastre și rulați ruterul.
Acum, să creăm câteva template-uri, acest lucru se poate face oriunde, puteți crea un subfolder în interiorul client
folderul numit șabloane și să creeze un fișier HTML separat pentru fiecare, dar din moment ce acestea vor fi șabloane scurte și doar pentru scopuri, de exemplu, le voi pune împreună într-un fișier numit "templates.html
' în interiorul 'client
":
Aceasta este Pagina de pornire
Pagina de profil
Bine ați revenit username
Pagina de contact
Contactați-mă pe twitter la twitterName
Primul șablon este destul de simplu, conține doar un mic cod HTML pentru titlul paginii de pornire. Cel de-al doilea șablon este foarte asemănător cu primul șablon, dar de data aceasta folosim nume de utilizator
parametru de traseu. Acum, ultimul șablon folosește de asemenea un substituent, dar ruta nu are twitterName
segment. Acest lucru se datorează faptului că reprezentanțele standard Meteor vor funcționa și vor funcționa în mod reactiv.
Înapoi în interiorul client
dosar, să creați acum un fișier numit "templates.js
", pentru a declara substituentul de contact.
Template.contactTemplate.twitterName = funcția () Session.setDefault ('twitter_name', '@ gabrielmanricks'); retur Session.get ("twitter_name");
Ați fi putut întoarce un șir, dar am vrut să demonstrez că totul este încă reactiv. Ultimul pas este ștergerea fișierelor implicite html și js din directorul rădăcină (în cazul în care sunt numite routerdemo.html și routerdemo.js). Cu aceasta ați terminat, porniți serverul Meteor și navigați la rutele date.
Încercați să mergeți la "/Acasă
"sau"utilizator / gmanricks
"sau"/a lua legatura
"și toate ar trebui să funcționeze pentru dvs. așa cum era de așteptat. Un alt lucru este că, deoarece am stocat numele de twitter în sesiune, putem deschide consola browserului pe pagina de contact și introduceți:
Session.set ("twitter_name", "@nettuts");
Și veți vedea că pagina va fi actualizată în timp real!
În acest articol, am construit o bibliotecă de bază a router-ului, în timp ce îi dăm încă o întorsătură Meteor. Am acoperit o mulțime de concepte de bază și, după cum se dovedește, o mulțime de concepte Underscore, de asemenea.
În cele din urmă, sper că am primit mesajul că nu există o adevărată "magie" care să se întâmple aici. Este vorba despre punerea în aplicare a ceea ce aveți nevoie, spre deosebire de ceea ce puteți.
Mulțumesc că ai citit, sper că ți-a plăcut. Ca întotdeauna, dacă aveți întrebări, le puteți lăsa mai jos sau puteți să mă întrebați pe IRC NetTuts sau pe Twitter.
Notă: Dacă sunteți interesat să aflați mai multe despre Meteor, tocmai am lansat noua mea carte, care detaliază procesul de construire a unei aplicații de la concepția sa și de planificare la securizare și implementare. Puteți prelua cartea atât în format ebook, cât și în softcover de la Amazon.