Crearea unui site cu mai multe pagini cu Meteor

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.


Caracteristici ale bibliotecii

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

  • Abilitatea de a încărca pagini diferite în funcție de URI
  • Citirea parametrilor din URI (substituenți)
  • Păstrarea dinamică a paginilor conform standardului Meteor

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.

Cedare psihica

Apoi, să descompunem proiectul în diferite secțiuni, astfel încât să știm la ce caracteristici trebuie să lucrăm.

  • Vom începe prin a obține URI-ul paginii curente, deoarece trebuie să potrivim rutele cu ceva. Acest lucru se poate face, cu ușurință, folosind window.location.pathname variabilă, furnizată de browser.
  • Apoi, avem nevoie de abilitatea de a adăuga rute. Acest lucru este, de asemenea, destul de simplu acum că am făcut un exemplu de cod; vom avea o funcție numită 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.
  • Cu URI curent și o serie de rute stocate, vom avea nevoie de un fel de metodă pentru a vedea dacă se potrivesc.
  • Și nu în ultimul rând, va trebui să luăm un traseu corespunzător și să afișăm șablonul atașat.

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.


Configurare

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


Potriviți rutele

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.

Setarea variabilei URI

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.

Adăugarea de rute

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.

Se potrivește o ruta cu un URI

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


Afișarea șablonului

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

Metoda de rulare

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.

Testează-l

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.

Crearea șabloanelor noastre

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":

  

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!


rezumat

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

Cod