acest tutorial este primul dintr-o serie de trei părți pe React de Brad Westfall. Când Brad mi-a arătat acest lucru, el a subliniat că există o mulțime de tutoriale despre începerea în React, dar nu la fel de mult despre unde să mergem de acolo. Dacă sunteți nou să reacționați, vă recomand să vizionați acest videoclip introductiv. Această serie preia în cazul în care elementele de bază lasă off.
- serie de articole:
- Cod serie
- React-Router
- rute Multiple
- aspect reutilizabil
- rute imbricate
- IndexRoutes
- atribute opționale de traseu
- utilizați <Link> nu <a>
- link-uri Active
- istoricul browserului
- redirecționare cu browserHistory
- potrivirea rutelor
- Router Demo
- ES6
- gruparea cu webpack și Babel
- aveți grijă la sintaxa depreciată
- rezumat
- serie de articole:
serie de articole:
- React Router (sunteți aici!)
- Componente Container
- Redux
Atenție! Acest articol a fost scris pre-React Router 4, care a devenit o alegere mai standard pentru rutare în React. Există un nou articol care acoperă React Router 4 aici ar trebui să citiți cu siguranță.
când învățam pentru prima dată, am găsit o mulțime de ghiduri pentru începători (adică 1, 2, 3, 4) care arătau cum să fac componente unice și să le redau domului. Ei au făcut o treabă bună de predare elementele de bază, cum ar fi JSX și recuzită, dar m – am luptat cu imaginind cum funcționează React în imaginea de ansamblu-ca o aplicație unică pagină din lumea reală (SPA). Deoarece această serie acoperă o mulțime de materiale, nu va acoperi conceptele absolute pentru începători. În schimb, va începe cu presupunerea că înțelegeți deja cum să creați și să redați cel puțin o componentă.
pentru ceea ce merită, iată câteva alte ghiduri grozave care vizează începătorii:
- reacționează.js și cum se potrivește cu orice altceva?
- Regândirea (Industrie) Cele Mai Bune Practici
- React.JS introducere pentru cei care știu doar suficient jQuery Pentru a obține de
Cod serie
această serie, de asemenea, vine cu unele Cod să se joace cu la GitHub. De-a lungul seriei, vom construi un SPA de bază axat pe utilizatori și widget-uri.
pentru a păstra lucrurile simple și scurte, exemplele din această serie vor începe prin a presupune că React și React Router sunt preluate de pe un CDN. Deci nu veți vedea require()
sau import
în exemplele imediate de mai jos. Spre sfârșitul acestui tutorial, însă, vom introduce Webpack și Babel pentru ghidurile GitHub. În acel moment, totul este ES6!
React-Router
React nu este un cadru, este o bibliotecă. Prin urmare, nu rezolvă toate nevoile unei aplicații. Face o treabă excelentă la crearea componentelor și la furnizarea unui sistem de gestionare a statului, dar crearea unui SPA mai complex va necesita o distribuție de sprijin. Primul pe care îl vom analiza este React Router.
dacă ați folosit vreun router front-end înainte, multe dintre aceste concepte vor fi familiare. Dar, spre deosebire de orice alt router pe care l-am folosit înainte, React Router folosește JSX, care ar putea părea puțin ciudat la început.
ca un primer, aceasta este ceea ce este ca pentru a face o singură componentă:
var Home = React.createClass({ render: function() { return (<h1>Welcome to the Home Page</h1>); }});ReactDOM.render(( <Home />), document.getElementById('root'));
Iată cum ar fi redată componenta Home
cu routerul React:
...ReactDOM.render(( <Router> <Route path="/" component={Home} /> </Router>), document.getElementById('root'));
rețineți că <Router>
și <Route>
sunt două lucruri diferite. Ele sunt componente reacționează punct de vedere tehnic, dar ele nu creează de fapt DOM ei înșiși. Deși poate părea că <Router>
în sine este redat la 'root'
, de fapt definim doar reguli despre modul în care funcționează aplicația noastră. Mergând mai departe, veți vedea adesea acest concept: componentele există uneori nu pentru a crea ele însele DOM, ci pentru a coordona alte componente care fac.
în exemplu, <Route>
definește o regulă în care vizitarea paginii de pornire /
va face componenta Home
în 'root'
.
rute Multiple
în exemplul anterior, traseul unic este foarte simplu. Nu ne dă prea multă valoare, deoarece am avut deja capacitatea de a reda componenta Home
fără ca routerul să fie implicat.
puterea routerului React vine atunci când folosim mai multe rute pentru a defini ce componentă ar trebui să redea pe baza căii active în prezent:
ReactDOM.render(( <Router> <Route path="/" component={Home} /> <Route path="/users" component={Users} /> <Route path="/widgets" component={Widgets} /> </Router>), document.getElementById('root'));
fiecare <Route>
va reda componenta respectivă atunci când calea sa se potrivește cu adresa URL. Doar una dintre aceste trei componente va fi redată în 'root'
la un moment dat. Cu această strategie, montăm routerul la DOM 'root'
o dată, apoi componentele de schimb ale routerului intră și ies cu modificări ale rutei.
de asemenea, merită remarcat faptul că routerul va schimba rutele fără a face cereri către server, deci imaginați-vă că fiecare componentă ar putea fi o pagină cu totul nouă.
aspect reutilizabil
începem să vedem începuturile umile ale unei aplicații cu o singură pagină. Cu toate acestea, încă nu rezolvă problemele din lumea reală. Sigur, am putea construi cele trei componente pentru a fi pagini HTML complete, dar ce zici de reutilizarea codului? Șansele sunt, aceste trei componente împărtășesc active comune, cum ar fi un antet și o bară laterală, deci cum prevenim repetarea HTML în fiecare componentă?
să ne imaginăm că construim o aplicație web care seamănă cu această machetă:
când începeți să vă gândiți la modul în care această machetă poate fi împărțită în secțiuni reutilizabile, s-ar putea să ajungeți la această idee:
gândirea în termeni de componente și machete nestabile ne va permite să creăm piese reutilizabile.
dintr-o dată, Departamentul de artă vă permite să știți că aplicația are nevoie de o pagină pentru căutarea widget-uri care seamănă cu pagina pentru căutarea utilizatorilor. Cu lista de utilizatori și lista de Widget-uri care necesită același” aspect ” pentru pagina lor de căutare, ideea de a avea aspectul de căutare ca o componentă separată are și mai mult sens acum:
aspect de căutare poate fi un șablon părinte pentru toate tipurile de pagini de căutare acum. Și în timp ce unele pagini ar putea avea nevoie de aspect de căutare, altele pot folosi direct aspectul principal fără ea:
aceasta este o strategie comună și dacă ați folosit orice sistem templating, ați făcut, probabil, ceva foarte similar. Acum să lucrăm la HTML. Pentru a începe, vom face HTML static fără a lua în considerare JavaScript:
<div> <!-- Main Layout --> <div class="app"> <header class="primary-header"><header> <aside class="primary-aside"></aside> <main> <!-- Search Layout --> <div class="search"> <header class="search-header"></header> <div class="results"> <!-- User List --> <ul class="user-list"> <li>Dan</li> <li>Ryan</li> <li>Michael</li> </ul> </div> <div class="search-footer pagination"></div> </div> </main> </div></div>
amintiți-vă, elementul 'root'
va fi întotdeauna prezent, deoarece este singurul element pe care corpul HTML inițial îl are înainte de a începe JavaScript. Cuvântul „rădăcină” este adecvat, deoarece întreaga noastră aplicație React se va monta la ea. Dar nu există „nume corect” sau convenție la ceea ce îl numiți. Am ales „root”, așa că vom continua să-l folosească de-a lungul exemplelor. Aveți grijă doar că montarea directă la elementul <body>
este foarte descurajată.
după crearea HTML-ului static, convertiți-l în componente React:
var MainLayout = React.createClass({ render: function() { // Note the `className` rather than `class` // `class` is a reserved word in JavaScript, so JSX uses `className` // Ultimately, it will render with a `class` in the DOM return ( <div className="app"> <header className="primary-header"><header> <aside className="primary-aside"></aside> <main> {this.props.children} </main> </div> ); }});var SearchLayout = React.createClass({ render: function() { return ( <div className="search"> <header className="search-header"></header> <div className="results"> {this.props.children} </div> <div className="search-footer pagination"></div> </div> ); }});var UserList = React.createClass({ render: function() { return ( <ul className="user-list"> <li>Dan</li> <li>Ryan</li> <li>Michael</li> </ul> ); }});
nu vă distrați prea mult între ceea ce numesc „aspect” vs „componentă”. Toate cele trei sunt componente React. Am ales să numesc două dintre ele” machete”, deoarece acesta este rolul pe care îl îndeplinesc.
vom folosi în cele din urmă „rute imbricate” pentru a plasa UserList
în interiorul SearchLayout
, apoi în interiorul MainLayout
. Dar mai întâi, observați că atunci când UserList
este plasat în interiorul părintelui său SearchLayout
, părintele va folosi this.props.children
pentru a determina locația sa. Toate componentele au this.props.children
ca recuzită, dar numai atunci când componentele sunt imbricate, componenta părinte primește acest recuzită completat automat de React. Pentru componentele care nu sunt componente părinte, this.props.children
va fi null
.
rute imbricate
Deci, cum facem ca aceste componente să cuibărească? Routerul o face pentru noi când cuibărim rute:
ReactDOM.render(( <Router> <Route component={MainLayout}> <Route component={SearchLayout}> <Route path="users" component={UserList} /> </Route> </Route> </Router>), document.getElementById('root'));
componentele vor fi imbricate în funcție de modul în care routerul își cuibărește rutele. Când utilizatorul vizitează ruta /users
, ruterul React va plasa componenta UserList
în interiorul SearchLayout
și apoi ambele în interiorul MainLayout
. Rezultatul final al vizitei /users
va fi cele trei componente imbricate plasate în interiorul 'root'
.
observați că nu avem o regulă pentru momentul în care utilizatorul vizitează calea paginii de pornire (/
) sau dorește să caute widget-uri. Acestea au fost lăsate în afara simplității, dar să le punem cu noul router:
ReactDOM.render(( <Router> <Route component={MainLayout}> <Route path="/" component={Home} /> <Route component={SearchLayout}> <Route path="users" component={UserList} /> <Route path="widgets" component={WidgetList} /> </Route> </Route> </Router>), document.getElementById('root'));
probabil ați observat până acum că JSX urmează regulile XML în sensul că componenta Route
poate fi scrisă fie ca o etichetă: <Route />
, fie ca două: <Route>...</Route>
. Acest lucru este valabil pentru toate JSX, inclusiv componentele personalizate și nodurile DOM normale. De exemplu, <div />
este JSX valid și se va converti la <div></div>
când este redat.
pentru concizie, imaginați-vă WidgetList
seamănă cu UserList
.
deoarece <Route component={SearchLayout}>
are două rute pentru copii acum, utilizatorul poate vizita /users
sau /widgets
și <Route>
corespunzător își va încărca componentele respective în interiorul componentei SearchLayout
.
de asemenea, observați cum componenta Home
va fi plasată direct în MainLayout
fără ca SearchLayout
să fie implicată — din cauza modului în care <Route>
sunt imbricate. Probabil vă puteți imagina că este ușor să rearanjați modul în care aspectele și componentele sunt imbricate prin rearanjarea rutelor.
IndexRoutes
React Router este foarte expresiv și de multe ori există mai multe moduri de a face același lucru. De exemplu, am fi putut scrie și routerul de mai sus astfel:
ReactDOM.render(( <Router> <Route path="/" component={MainLayout}> <IndexRoute component={Home} /> <Route component={SearchLayout}> <Route path="users" component={UserList} /> <Route path="widgets" component={WidgetList} /> </Route> </Route> </Router>), document.getElementById('root'));
în ciuda aspectului său diferit, ambele funcționează exact în același mod.
atribute opționale de traseu
uneori, <Route>
va avea un atribut component
fără path
, ca în SearchLayout
traseu de sus. Alteori, ar putea fi necesar să avem un <Route>
cu un path
și nu component
. Pentru a vedea de ce, să începem cu acest exemplu:
<Route path="product/settings" component={ProductSettings} /><Route path="product/inventory" component={ProductInventory} /><Route path="product/orders" component={ProductOrders} />
porțiunea /product
a path
este repetitivă. Putem elimina repetarea prin împachetarea tuturor celor trei rute într – o nouă <Route>
:
<Route path="product"> <Route path="settings" component={ProductSettings} /> <Route path="inventory" component={ProductInventory} /> <Route path="orders" component={ProductOrders} /></Route>
din nou, React Router își arată expresivitatea. Quiz: ați observat problema cu ambele soluții? În acest moment nu avem reguli pentru momentul în care utilizatorul vizitează calea /product
.
pentru a remedia acest lucru, putem adăuga un IndexRoute
:
<Route path="product"> <IndexRoute component={ProductProfile} /> <Route path="settings" component={ProductSettings} /> <Route path="inventory" component={ProductInventory} /> <Route path="orders" component={ProductOrders} /></Route>
utilizați <Link>
nu <a>
când creați ancore pentru rutele dvs., va trebui să utilizați <Link to="">
în loc de <a href="">
. Nu vă faceți griji, totuși, atunci când utilizați componenta <Link>
, routerul React vă va oferi în cele din urmă o ancoră obișnuită în DOM. Utilizarea <Link>
deși este necesar pentru React Router pentru a face o parte din magia de rutare.
să adăugăm niște legături (ancore) la MainLayout
:
var MainLayout = React.createClass({ render: function() { return ( <div className="app"> <header className="primary-header"></header> <aside className="primary-aside"> <ul> <li><Link to="/">Home</Link></li> <li><Link to="/users">Users</Link></li> <li><Link to="/widgets">Widgets</Link></li> </ul> </aside> <main> {this.props.children} </main> </div> ); }});
atributele componentelor <Link>
vor fi transmise către ancora pe care o creează. Deci acest JSX:
<Link to="/users" className="users">
va deveni acest lucru în DOM:
<a href="/users" class="users">
dacă trebuie să creați o ancoră pentru căi non-router, cum ar fi un site web extern, utilizați etichetele normale de ancorare ca de obicei. Pentru mai multe informații, consultați documentația pentru IndexRoute și Link.
link-uri Active
o caracteristică interesantă a componentei <Link>
este capacitatea sa de a ști când este activă:
<Link to="/users" activeClassName="active">Users</Link>
dacă utilizatorul se află pe calea /users
, routerul va căuta ancore potrivite care au fost realizate cu <Link>
și va comuta clasa lor active
. Vezi mai multe despre această caracteristică.
istoricul browserului
pentru a preveni confuzia, am omis un detaliu important până acum. <Router>
trebuie să știe ce strategie de urmărire a istoricului să folosească. React Router docs recomandă browserHistory care este implementat după cum urmează:
var browserHistory = ReactRouter.browserHistory;ReactDOM.render(( <Router history={browserHistory}> ... </Router>), document.getElementById('root'));
în versiunile anterioare ale React Router, history
atribut nu a fost necesară și implicit a fost de a utiliza hashHistory. După cum sugerează și numele, a folosit un semn hash #
în adresa URL pentru a gestiona rutarea în stil SPA front-end, similar cu ceea ce v-ați putea aștepta de la o coloană vertebrală.JS router.
cu hashHistory
, adresele URL vor arăta astfel:
- example.com
- example.com/#/users?_k=ckuvup
- example.com/#/widgets?_k=ckuvup
ce se întâmplă cu acele șiruri de interogare urâte?
când browserHistory
este implementat, căile arată mai organic:
- example.com
- example.com/users
- exemplu.com / widgets
există un avertisment, deși pe server atunci când browserHistory
este utilizat pe front-end. Dacă utilizatorul își începe vizita la example.com
și apoi navighează la /users
și /widgets
, React Router gestionează acest scenariu așa cum era de așteptat. Cu toate acestea, dacă utilizatorul își începe vizita tastând example.com/widgets
direct în browser sau dacă se actualizează pe example.com/widgets
, atunci browserul trebuie să facă cel puțin o solicitare către server pentru /widgets
. Dacă nu există un router server-side, deși, acest lucru va livra o 404:
pentru a rezolva problema 404 de pe server, React Router recomandă un router wildcard pe partea de server. Cu această strategie, indiferent de ruta server-side se numește, serverul ar trebui să servească întotdeauna același fișier HTML. Apoi, dacă utilizatorul pornește direct la example.com/widgets
, chiar dacă același fișier HTML este returnat, React Router este suficient de inteligent pentru a încărca componenta corectă.
utilizatorul nu va observa nimic ciudat, dar este posibil să aveți îngrijorări cu privire la servirea întotdeauna a aceluiași fișier HTML. În exemplele de cod, această serie va continua să utilizeze strategia „router wildcard”, dar depinde de dvs. să gestionați rutarea de pe server în moduri pe care le considerați potrivite.
routerul React poate fi utilizat atât pe partea de server, cât și pe partea de client într-un mod izomorf? Sigur că se poate, dar asta depășește cu mult domeniul de aplicare al acestui tutorial.
redirecționare cu browserHistory
browserHistory
obiectul este un singleton, astfel încât să îl puteți include în oricare dintre fișierele dvs. Dacă trebuie să redirecționați manual utilizatorul în oricare dintre codul dvs., puteți utiliza metoda push
pentru a face acest lucru:
browserHistory.push('/some/path');
potrivirea rutelor
routerul React gestionează potrivirea rutelor în mod similar cu alte routere:
<Route path="users/:userId" component={UserProfile} />
acest traseu se va potrivi atunci când utilizatorul vizitează orice cale care începe cu users/
și are orice valoare după aceea. Se va potrivi cu /users/1
, /users/143
sau chiar /users/abc
(pe care va trebui să îl validați singur).
React Router va trece valoarea pentru :userId
ca recuzită la UserProfile
. Această recuzită este accesată ca this.props.params.userId
în interiorul UserProfile
.
Router Demo
în acest moment, avem suficient cod pentru a afișa un demo.
a se vedea Pen React-Router Demo de Brad Westfall (@bradwestfall) pe CodePen.
dacă ați făcut clic pe câteva rute din exemplu, este posibil să observați că butoanele Înapoi și înainte ale browserului funcționează cu routerul. Acesta este unul dintre principalele motive pentru care există aceste strategii history
. De asemenea, rețineți că, cu fiecare traseu pe care îl vizitați, nu există solicitări către server, cu excepția primului care obține codul HTML inițial. Cât de tare e asta?
ES6
în exemplul CodePen, React
, ReactDOM
și ReactRouter
sunt variabile globale dintr-un CDN. În interiorul obiectului ReactRouter
sunt tot felul de lucruri de care avem nevoie, cum ar fi componentele Router
și Route
. Deci, am putea folosi ReactRouter
ca aceasta:
ReactDOM.render(( <ReactRouter.Router> <ReactRouter.Route ... /> </ReactRouter.Router>), document.getElementById('root'));
aici, trebuie să prefixăm toate componentele routerului nostru cu obiectul părinte ReactRouter
. Sau am putea folosi noua sintaxă destructuring ES6 ca aceasta:
var { Router, Route, IndexRoute, Link } = ReactRouter
aceasta „extrage” părți din ReactRouter
în variabile normale, astfel încât să le putem accesa direct.
începând de acum, exemplele din această serie vor folosi o varietate de sintaxe ES6, inclusiv destructurarea, operatorul de răspândire, importurile/exporturile și, probabil, altele. Va exista o scurtă explicație a fiecărei noi sintaxe pe măsură ce apar, iar repo-ul GitHub care vine cu această serie are, de asemenea, o mulțime de explicații ES6.
gruparea cu webpack și Babel
după cum sa menționat anterior, această serie vine cu un repo GitHub astfel încât să puteți experimenta cu cod. Deoarece se va asemăna cu crearea unui SPA din lumea reală, va folosi instrumente precum webpack și Babel.
- webpack grupează mai multe fișiere JavaScript într-un singur fișier pentru browser.
- Babel va converti codul ES6 (ES2015) în ES5, deoarece majoritatea browserelor nu înțeleg încă toate ES6. Ca acest articol vârstele, browsere va sprijini ES6 și Babel nu pot fi necesare.
dacă nu sunteți încă prea confortabil folosind aceste instrumente, nu vă faceți griji, Codul De exemplu are deja totul de configurare, astfel încât să vă puteți concentra pe React. Dar asigurați – vă că pentru a revizui codul de exemplu README.md fișier pentru documentația suplimentară a fluxului de lucru.
aveți grijă la sintaxa depreciată
căutarea pe Google a informațiilor despre routerul React vă poate ateriza pe unul dintre numeroasele articole sau pagini StackOverflow care au fost scrise când routerul React a fost în versiunea sa pre-1.0. Multe caracteristici din pre-1.0 eliberare sunt depreciate acum. Iată o listă scurtă:
-
<Route name="" />
este învechit. Utilizați<Route path="" />
în schimb. -
<Route handler="" />
este învechit. Utilizați<Route component="" />
în schimb. -
<NotFoundRoute />
este învechit. A se vedea alternativa -
<RouteHandler />
este învechită. -
willTransitionTo
este învechit. A se vedea onEnter -
willTransitionFrom
este învechit. A se vedea onLeave - „locații” sunt acum numite „istorii”.
a se vedea lista completă pentru 1.0.0 și 2.0.0
rezumat
există încă mai multe caracteristici în React Router care nu au fost afișate, astfel încât să fie sigur de a verifica documentele API. Creatorii React Router au creat, de asemenea, un tutorial pas cu pas pentru React Router și, de asemenea, checkout acest React.JS Conf Video despre modul în care a fost creat React Router.
Mulțumiri speciale lui Lynn Fisher pentru opera de artă @lynnandtonic
serie de articole:
- React Router (sunteți aici!)
- Componente Container
- Redux