Tasoitus react: React Router

tämä opetusohjelma on ensimmäinen Brad Westfallin kolmiosaisesta React-sarjasta. Kun Brad pystytti minulle tämän, hän huomautti, että on olemassa hyvä määrä tutorials getting started in React, mutta ei niin paljon siitä, missä mennä sieltä. Jos olet aivan uusi reagoimaan, suosittelen katsomaan tämän intro-videon. Tässä sarjassa jatketaan siitä, mihin perusasiat jäävät.

artikkelisarja:

  1. React Router (olet täällä!)
  2. Säiliökomponentit
  3. Redux

Varoitus! Tämä artikkeli on kirjoitettu Pre-React-reitittimeen 4, josta on tullut Reactissa vakiovalinta reititykselle. On uusi artikkeli kattaa React Router 4 täällä kannattaa ehdottomasti lukea.

kun olin ensimmäistä kertaa oppimassa, löysin paljon aloittelijan oppaita (eli 1, 2, 3, 4), jotka osoittivat, miten tehdään yksittäisiä komponentteja ja renderoidaan ne DOM: iin. He opettivat hienosti perusasiat, kuten JSX: n ja rekvisiitan, mutta kamppailin sen kanssa, miten React toimii isommassa kuvassa – kuin tosielämän yhden sivun sovellus (SPA). Koska tämä sarja kattaa paljon materiaalia, se ei kata ehdotonta aloittelija käsitteitä. Sen sijaan, se alkaa oletuksella, että ymmärrät jo miten luoda ja tehdä ainakin yksi komponentti.

For what it ’ s worth, here are some other great guides that tähtää beginners:

  • reagoi.miten se sopii kaikkeen muuhun?
  • Alan Parhaiden Käytäntöjen Uudelleenarviointi
  • Reagoi.JS-esittely ihmisille, jotka tietävät juuri sen verran jQuerya, että pääsevät

sarjan koodi

tämän sarjan mukana tulee myös jonkinlainen koodi, jolla voi pelata GitHubissa. Koko sarjan ajan rakennamme peruskylpylää, joka keskittyy käyttäjien ja vekottimien ympärille.

jotta asiat pysyisivät yksinkertaisina ja lyhyinä, tämän sarjan esimerkit alkavat olettamalla, että React ja React-reititin on haettu CDN: ltä. Et siis näe require() tai import alla olevissa välittömissä esimerkeissä. Loppupuolella tämän opetusohjelman kuitenkin, esittelemme Webpack ja Babel varten GitHub oppaita. Siinä vaiheessa kaikki on ES6!

React-reititin

React ei ole kehys, se on kirjasto. Siksi se ei ratkaise kaikkia sovelluksen tarpeita. Se tekee hienoa työtä komponenttien luomisessa ja järjestelmän tarjoamisessa valtion hallintaan, mutta monimutkaisemman kylpylän luominen vaatii tukivalun. Ensimmäinen, että tarkastelemme on React Router.

jos olet aiemmin käyttänyt jotain etupään reititintä, monet näistä käsitteistä ovat tuttuja. Mutta toisin kuin mikään muu reititin olen käyttänyt ennen, React reititin käyttää JSX, joka saattaa näyttää hieman oudolta aluksi.

alukkeena tällainen on yhden komponentin renderointi:

var Home = React.createClass({ render: function() { return (<h1>Welcome to the Home Page</h1>); }});ReactDOM.render(( <Home />), document.getElementById('root'));

näin Home – komponentti renderöitäisiin React-reitittimellä:

...ReactDOM.render(( <Router> <Route path="/" component={Home} /> </Router>), document.getElementById('root'));

huomaa, että <Router> ja <Route> ovat kaksi eri asiaa. Ne ovat teknisesti React-komponentteja, mutta ne eivät itse luo Domia. Vaikka voi näyttää siltä, että <Router> itse on renderöity 'root': lle, Olemme itse asiassa vain määrittelemässä sääntöjä siitä, miten sovelluksemme toimii. Eteenpäin, näet tämän konseptin usein: komponentit joskus olemassa ei luoda DOM itse, mutta koordinoida muita komponentteja, jotka tekevät.

esimerkissä <Route> määritellään sääntö, jossa käynti kotisivulla / muuttaa Home – komponentin 'root': ksi.

useita reittejä

edellisessä esimerkissä yksittäinen reitti on hyvin yksinkertainen. Se ei anna meille paljon arvoa, koska meillä oli jo kyky tehdä Home – komponentti ilman, että reititin oli mukana.

React Routerin teho tulee, kun käytämme useita reittejä määrittääksemme, mikä komponentti pitäisi renderöidä sen perusteella, mikä polku on tällä hetkellä aktiivinen:

ReactDOM.render(( <Router> <Route path="/" component={Home} /> <Route path="/users" component={Users} /> <Route path="/widgets" component={Widgets} /> </Router>), document.getElementById('root'));

kukin <Route> esittää vastaavan komponenttinsa, kun sen polku vastaa URL-osoitetta. Vain yksi näistä kolmesta komponentista renderöidään 'root': ään kulloinkin. Tällä strategialla kiinnitämme reitittimen Dom 'root' kerran, sitten reitittimen vaihtokomponentit sisään ja ulos reittimuutoksilla.

on myös syytä huomata, että reititin vaihtaa reittejä tekemättä palvelimelle pyyntöjä, joten kuvitelkaa, että jokainen komponentti voisi olla kokonaan uusi sivu.

Re-usable Layout

alamme nähdä yksisivuisen sovelluksen vaatimattomia alkuja. Se ei kuitenkaan vieläkään ratkaise reaalimaailman ongelmia. Toki voisimme rakentaa kolme komponenttia täyteen HTML-sivuja, mutta entä koodin uudelleenkäyttö? Mahdollisuudet ovat, nämä kolme komponenttia jakavat yhteisiä resursseja, kuten otsikko ja sivupalkissa, Joten miten estää HTML toistoa kunkin komponentin?

kuvitellaan, että rakennamme verkkosovellusta, joka muistutti tätä mallikappaletta:

yksinkertainen sivusto mockup.

kun alkaa miettiä, miten tämä mallikappale voidaan jakaa uudelleen käytettäviin osiin, saattaa päätyä tähän ajatukseen:

miten voit hajottaa yksinkertainen web mockup osioihin.

säilyvien osien ja asettelujen ajattelu mahdollistaa uudelleenkäytettävien osien luomisen.

yhtäkkiä taideosasto kertoo, että sovellus tarvitsee hakusivua muistuttavan sivun etsijöiden etsimiseen. Käyttäjäluettelon ja Widget Luettelo molemmat vaativat saman ”näyttää” niiden hakusivulle, ajatus on haku Layout erillisenä komponenttina on vieläkin järkevämpää nyt:

Etsi widgettejä nyt käyttäjien sijasta, mutta vanhemmat osat pysyvät samoina.

Hakuasettelu voi olla nykyään vanhempapohjana kaikenlaisille hakusivuille. Ja vaikka jotkut sivut saattavat tarvita Hakuasettelua, toiset voivat suoraan käyttää Pääasettelua ilman sitä:

pohjapiirros irrotettu.

tämä on yleinen strategia ja jos on käyttänyt jotain temppeliherruusjärjestelmää, on todennäköisesti tehnyt jotain hyvin samankaltaista. Nyt työstetään HTML: ää. Aloittaa, teemme staattinen HTML harkitsematta 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>

muista ,että 'root' elementti on aina läsnä, koska se on ainoa elementti, joka alkuperäisessä HTML-rungossa on ennen JavaScriptin käynnistymistä. Sana ”juuri” on sopiva, koska koko Reaktiosovelluksemme liittyy siihen. Mutta ei ole olemassa” oikeaa nimeä ” tai sovinnaisuutta, miksi sitä kutsutaan. Olen valinnut ”root”, joten jatkamme käyttää sitä kaikissa esimerkeissä. Varokaa vain, että suoraan <body> – elementtiin kiinnittyminen on erittäin lannistavaa.

kun olet luonut staattisen HTML: n, muuta se Reaktiokomponenteiksi:

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> ); }});

älä saa liian hajamielinen välillä mitä kutsun ”Layout” vs ”komponentti”. Kaikki kolme ovat Reaktiokomponentteja. Valitsen vain kutsua kahta niistä ”layout”, koska se on rooli he suorittavat.

käytämme lopulta ”sisäkkäisiä reittejä” sijoittaaksemme UserList sisälle SearchLayout, sitten sisälle MainLayout. Mutta huomaa ensin, että kun UserList on sijoitettu emonsa SearchLayout sisään, emoyritys käyttää this.props.children sen sijainnin määrittämiseen. Kaikilla komponenteilla on this.props.children rekvisiittana, mutta vasta kun komponentit ovat sisäkkäisiä, kantakomponentti saa rekvisiittansa täytettyä automaattisesti reagoimalla. Sellaisten komponenttien osalta, jotka eivät ole kantakomponentteja, this.props.children on null.

pesivät reitit

joten miten saamme nämä komponentit pesimään? Reititin tekee sen meille, kun pesä reittejä:

ReactDOM.render(( <Router> <Route component={MainLayout}> <Route component={SearchLayout}> <Route path="users" component={UserList} /> </Route> </Route> </Router>), document.getElementById('root'));

komponentit pesiytyvät sen mukaan, miten reititin pesii reittinsä. Kun käyttäjä käy /users – reitillä, React-reititin sijoittaa UserList – komponentin SearchLayout: n sisälle ja sitten molemmat MainLayout: n sisälle. /users käynnin lopputuloksena on kolme sisäkkäistä komponenttia, jotka on sijoitettu 'root': n sisälle.

huomaa, että meillä ei ole sääntöä sille, milloin käyttäjä vierailee kotisivun polulla (/) tai haluaa etsiä widgettejä. Ne jätettiin yksinkertaisuuden vuoksi pois, mutta laitetaan ne uuteen reitittimeen:

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'));

olet varmaan jo huomannut, että JSX noudattaa XML-sääntöjä siinä mielessä, että Route – komponentti voidaan kirjoittaa joko yhtenä tagina: <Route /> tai kahtena: <Route>...</Route>. Tämä pätee kaikkiin JSX mukaan lukien mukautettuja komponentteja ja normaali Dom solmut. Esimerkiksi <div /> on kelvollinen JSX ja muuttuu renderöidessään muotoon <div></div>.

lyhyyden vuoksi vain kuvitella WidgetList muistuttaa UserList.

koska <Route component={SearchLayout}>: llä on nyt kaksi lapsireittiä, käyttäjä voi käydä /users tai /widgets ja vastaava <Route> Lataa omat komponenttinsa SearchLayout – komponentin sisään.

huomaa myös, miten Home komponentti sijoitetaan suoraan MainLayout: n sisälle ilman, että SearchLayouton mukana — koska <Route> s: t ovat sisäkkäisiä. Voit luultavasti kuvitella, että on helppo järjestää uudelleen, miten asettelut ja komponentit ovat sisäkkäisiä järjestämällä reitit uudelleen.

IndexRoutes

React Router on hyvin ekspressiivinen ja usein on useampi kuin yksi tapa tehdä sama asia. Esimerkiksi olisimme voineet myös kirjoittaa edellä reitittimen näin:

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'));

erilaisesta ulkonäöstään huolimatta molemmat toimivat täsmälleen samalla tavalla.

vapaaehtoiset Reittiominaisuudet

joskus <Route> on component attribuutti, jossa ei ole path, kuten SearchLayout reitti ylhäältä. Muina aikoina saatetaan tarvita <Route>, kun path ja ei component. Nähdäksesi miksi, aloitetaan tästä esimerkistä:

<Route path="product/settings" component={ProductSettings} /><Route path="product/inventory" component={ProductInventory} /><Route path="product/orders" component={ProductOrders} />

/product osuus path on toistuva. Voimme poistaa toistoa käärimällä kaikki kolme reittiä uuteen <Route>:

<Route path="product"> <Route path="settings" component={ProductSettings} /> <Route path="inventory" component={ProductInventory} /> <Route path="orders" component={ProductOrders} /></Route>

jälleen React-reititin näyttää ilmaisuvoimansa. Tietovisa: huomasitko ongelman molemmissa ratkaisuissa? Tällä hetkellä meillä ei ole sääntöjä siitä, milloin käyttäjä käy /product – polulla.

tämän korjaamiseksi voidaan lisätä IndexRoute:

<Route path="product"> <IndexRoute component={ProductProfile} /> <Route path="settings" component={ProductSettings} /> <Route path="inventory" component={ProductInventory} /> <Route path="orders" component={ProductOrders} /></Route>

käytä <Link> ei <a>

kun luot ankkureita reiteillesi, sinun on käytettävä <Link to=""> eikä <a href="">. Älä huoli, kun käytät <Link> – komponenttia, React-reititin antaa sinulle lopulta tavallisen ankkurin DOM: ssä. <Link> käyttäminen on kuitenkin välttämätöntä, jotta React-reititin voi tehdä osan reititystaioistaan.

Let ’ s add some link (anchors) to our 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> ); }});

<Link> komponenttien attribuutit siirtyvät niiden luomalle ankkurille. Joten tämä JSX:

<Link to="/users" className="users">

tulee tämä DOM:

<a href="/users" class="users">

jos sinun täytyy luoda ankkuri muille kuin reititinpoluille, kuten ulkopuoliselle verkkosivustolle, käytä normaaleja ankkuri-tunnisteita tavalliseen tapaan. Lisätietoja on Indexrouten dokumentaatiossa ja linkissä.

aktiiviset linkit

<Link> komponentin viileä ominaisuus on sen kyky tietää, milloin se on aktiivinen:

<Link to="/users" activeClassName="active">Users</Link>

jos käyttäjä on /users – polulla, reititin etsii yhteensopivat ankkurit, jotka on tehty <Link>: llä, ja se vaihtaa heidän active – luokkaansa. Katso lisää tästä ominaisuudesta.

selainhistoria

sekaannuksen estämiseksi olen jättänyt tähän asti tärkeän yksityiskohdan kertomatta. <Router> on tiedettävä, mitä historianseurantastrategiaa käytetään. React Router docs suosittelee browserHistory joka toteutetaan seuraavasti:

var browserHistory = ReactRouter.browserHistory;ReactDOM.render(( <Router history={browserHistory}> ... </Router>), document.getElementById('root'));

React Routerin aiemmissa versioissa history – attribuuttia ei vaadittu, vaan oletuksena oli käyttää hashhistorya. Kuten nimestä voi päätellä, se käytti # hash-merkkiä URL-osoitteessa hallitakseen front-end SPA-tyylistä reititystä, jollaista voisi odottaa Selkärangalta.JS router.

kanssa hashHistory URL-osoitteet näyttävät tältä:

  • example.com
  • example.com/#/users?_k=ckuvup
  • example.com/#/widgets?_k=ckuvup

mitäs nuo rumat kyselykielet sitten ovat?

kun browserHistory toteutetaan, polut näyttävät orgaanisemmilta:

  • example.com
  • example.com/users
  • esimerkki.com / widgetit

palvelimella on kuitenkin varoitus, kun browserHistory käytetään etupäässä. Jos käyttäjä aloittaa käyntinsä numerosta example.com ja siirtyy sen jälkeen arvoihin /users ja /widgets, React-reititin hoitaa tämän skenaarion odotetusti. Jos käyttäjä kuitenkin aloittaa vierailunsa kirjoittamalla example.com/widgets suoraan selaimeen tai jos ne päivittyvät example.com/widgets, selaimen on tehtävä palvelimelle vähintään yksi pyyntö /widgets. Jos palvelinpuolen reititintä ei kuitenkaan ole, tämä antaa 404:

varo URL-osoitteita. Tarvitset palvelinpuoleisen reitittimen.

404-ongelman ratkaisemiseksi palvelimelta React-reititin suosittelee yleismerkkireititintä palvelinpuolelle. Tämän strategian, riippumatta siitä, mitä palvelimen puolella reittiä kutsutaan, palvelimen pitäisi aina palvella samaa HTML-tiedostoa. Sitten jos käyttäjä aloittaa suoraan numerosta example.com/widgets, vaikka sama HTML-tiedosto palautetaan, React-reititin on tarpeeksi älykäs lataamaan oikean komponentin.

käyttäjä ei huomaa mitään outoa, mutta saattaa olla huolissaan aina saman HTML-tiedoston tarjoamisesta. Koodiesimerkeissä tämä sarja käyttää edelleen ”jokerimerkkireititintä”, mutta on sinun asiasi käsitellä palvelinpuolista reititystäsi parhaaksi katsomillasi tavoilla.

Voiko React-reititintä käyttää sekä palvelinpuolella että asiakaspuolella isomorfisesti? Toki se voi, mutta se on paljon soveltamisalan ulkopuolella tämän opetusohjelma.

uudelleenohjaus browserHistory

browserHistory objekti on singleton, joten voit sisällyttää sen mihin tahansa tiedostoosi. Jos sinun on ohjattava käyttäjä manuaalisesti johonkin koodiisi, voit käyttää sen push – menetelmää.:

browserHistory.push('/some/path');

Reittisovitus

React-reititin käsittelee reittisovitusta samalla tavalla kuin muutkin reitittimet:

<Route path="users/:userId" component={UserProfile} />

tämä reitti täsmää, kun käyttäjä käy millä tahansa polulla, joka alkaa numerolla users/ ja jolla on mitään arvoa jälkeenpäin. Se vastaa /users/1, /users/143 tai jopa /users/abc (joka sinun täytyy vahvistaa itse).

React-reititin siirtää arvon :userId rekvisiitaksi UserProfile. Tähän rekvisiittaan pääsee nimellä this.props.params.userId sisällä UserProfile.

Routidemo

tässä vaiheessa meillä on tarpeeksi koodia Demon näyttämiseksi.

See the Pen React-Router Demo by Brad Westfall (@bradwestfall) on CodePen.

jos klikkasit muutamia reittejä esimerkissä, saatat huomata, että selaimen selkä-ja eteenpäin-painikkeet toimivat reitittimen kanssa. Tämä on yksi tärkeimmistä syistä näiden history strategioiden olemassaoloon. Myös, pitää mielessä, että jokainen reitti käyt, ei ole pyyntöjä tehdään palvelimelle paitsi aivan ensimmäinen saada alkuperäisen HTML. Eikö olekin siistiä?

ES6

CodePen-esimerkissämme React, ReactDOM ja ReactRouter ovat globaaleja muuttujia CDN: stä. ReactRouter objektin sisällä on kaikenlaisia asioita, joita tarvitsemme, kuten Router ja Route komponentit. Joten voisimme käyttää ReactRouter näin:

ReactDOM.render(( <ReactRouter.Router> <ReactRouter.Route ... /> </ReactRouter.Router>), document.getElementById('root'));

Tässä Meidän on etuliitettävä kaikki reitittimemme komponentit niiden pääobjektilla ReactRouter. Tai voimme käyttää ES6: n uutta destructuring-syntaksia näin.:

var { Router, Route, IndexRoute, Link } = ReactRouter

tämä ”poimii” osia ReactRouter normaaleiksi muuttujiksi, jotta voimme käyttää niitä suoraan.

tästä lähtien tämän sarjan esimerkeissä käytetään erilaisia ES6-syntakseja, kuten destructuring, spread operator, import/exports, ja ehkä muita. Jokaisesta uudesta syntaksista tulee lyhyt selitys sitä mukaa kuin ne ilmestyvät ja tämän sarjan mukana tuleva GitHub repo sisältää myös paljon ES6-selityksiä.

niputtaminen webpackin ja Babelin kanssa

kuten aiemmin todettiin, tämän sarjan mukana tulee GitHub repo, joten voit kokeilla koodia. Koska se tulee muistuttamaan todellisen maailman kylpylän tekemisiä, se käyttää työkaluja, kuten webpackia ja Babelia.

  • webpack niputtaa useita JavaScript-tiedostoja yhdeksi tiedostoksi selaimelle.
  • Babel muuntaa ES6 (ES2015) – koodin ES5: ksi, koska useimmat selaimet eivät vielä ymmärrä kaikkea ES6: sta. Tämän artikkelin ikääntyessä selaimet tukevat ES6: ta, eikä Babelia välttämättä tarvita.

jos et ole vielä kovin mukava käyttää näitä työkaluja, älä huoli, esimerkkikoodissa on jo kaikki asetukset, joten voit keskittyä Reactiin. Mutta muista tarkistaa esimerkkikoodin README.md tiedosto työnkulun lisädokumentointia varten.

ole varovainen vanhentuneen syntaksin

hakeminen Googlelta saadaksesi tietoa React-reitittimestä saattaa päätyä jollekin niistä monista artikkeleista tai StackOverflow-sivuista, jotka on kirjoitettu React-reitittimen ollessa ennen 1.0-julkaisua. Monia ominaisuuksia pre-1.0 julkaisu on vanhentunut nyt. Tässä lyhyt lista:

  • <Route name="" /> on vanhentunut. Käytä <Route path="" /> sen sijaan.
  • <Route handler="" /> on vanhentunut. Käytä sen sijaan <Route component="" />.
  • <NotFoundRoute /> on vanhentunut. KS. vaihtoehto
  • <RouteHandler /> on vanhentunut.
  • willTransitionTo on vanhentunut. KS. kohta
  • willTransitionFrom on vanhentunut. Katso onLeave
  • ” paikkoja ”kutsutaan nykyään”historioiksi”.

Katso koko lista kohteista 1.0.0 ja 2.0.0

Yhteenveto

React-reitittimessä on vielä enemmän ominaisuuksia, joita ei näytetty, joten muista tarkistaa API-dokumentit. React Routerin luojat ovat myös luoneet vaiheittaisen opetusohjelman React Routerille ja myös checkout this Reactille.js Conf Video Miten React reititin luotiin.

erityiskiitokset Lynn Fisherille @ lynnandtonic

artikkelisarja:

  1. React Router (olet täällä!)
  2. Kontin Komponentit
  3. Redux

Vastaa

Sähköpostiosoitettasi ei julkaista.