Szintezés a React: React Router

ez a bemutató az első három részből álló sorozat reagál Brad Westfall. Amikor Brad hangú nekem ezt, rámutatott, van egy jó adag útmutatók az első lépések a React, de nem annyira, hogy hová menjen onnan. Ha teljesen új reagálni, azt javaslom, hogy nézze meg ezt az intro videót. Ez a sorozat ott folytatódik, ahol az alapok abbahagyják.

cikksorozat:

  1. React Router (Ön itt van!)
  2. Konténer Alkatrészek
  3. Redux

Figyelem! Ezt a cikket a pre-React Router 4 írta, amely a React routing szabványosabb választásává vált. Van egy új cikk, amely a React routerre vonatkozik 4 itt feltétlenül olvassa el.

amikor először tanultam, sok kezdő útmutatót találtam (pl. 1, 2, 3, 4), amelyek megmutatták, hogyan lehet egyedi komponenseket készíteni és azokat a DOM-nak megjeleníteni. Jó munkát végeztek az alapok tanításában, mint a JSX és a kellékek, de küzdöttem azzal, hogy kitaláljam, hogyan működik a React a nagyobb képen – mint egy valós egyoldalas alkalmazás (SPA). Mivel ez a sorozat sok anyagot fed le, nem fogja lefedni az abszolút kezdő fogalmakat. Ehelyett azzal a feltevéssel kezdődik, hogy már megértette, hogyan kell létrehozni és megjeleníteni legalább egy összetevőt.

amit érdemes, itt van néhány más nagy útmutatók, amelyek célja a kezdők:

  • reagálj.js és hogyan illeszkedik minden máshoz?
  • A Bevált Gyakorlatok Újragondolása
  • Reagáljon.js Bevezetés Az emberek, akik tudják, csak annyi jQuery, hogy a

sorozat kód

ez a sorozat is jön néhány kódot játszani a GitHub. A sorozat során egy alapvető SPA-t építünk a felhasználók és a widgetek köré.

hogy a dolgok egyszerűek és rövidek legyenek, a sorozat példái azzal kezdődnek, hogy feltételezzük, hogy a React és a React Router egy CDN-ből származik. Tehát nem fogja látni require() vagy import az alábbi közvetlen példákban. Ennek az oktatóanyagnak a vége felé azonban bemutatjuk a Webpack-et és a Babelt a GitHub útmutatókhoz. Ezen a ponton, ez mind ES6!

React-Router

a React nem keretrendszer, hanem könyvtár. Ezért nem oldja meg az alkalmazás összes igényét. Nagyszerű munkát végez az összetevők létrehozásában és az állam kezelésére szolgáló rendszer biztosításában, de egy összetettebb SPA létrehozásához támogató szereplőkre lesz szükség. Az első, amit megnézünk, a React Router.

ha korábban már használt front-end routert, ezek közül a fogalmak közül sok ismerős lesz. De ellentétben bármely más útválasztóval, amelyet korábban használtam, a React Router JSX-et használ, ami eleinte kissé furcsának tűnhet.

mint alapozó, ez az, amit ez, mint hogy egyetlen komponenst:

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

így jelenik meg a Home összetevő a React routerrel:

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

a <Router> és <Route> két különböző dolog. Technikailag React komponensek, de valójában nem maguk hozzák létre a DOM-ot. Bár úgy tűnhet, hogy maga a <Router> jelenik meg a 'root' – hoz, valójában csak szabályokat határozunk meg az alkalmazás működéséről. Előre haladva gyakran látni fogja ezt a koncepciót: az összetevők néha nem azért léteznek, hogy maguk hozzák létre a DOM-ot, hanem hogy összehangolják a többi összetevőt.

a példában a <Route> meghatároz egy szabályt, ahol a / Kezdőlap meglátogatása a Homeösszetevőt a 'root' – ba teszi.

több útvonal

az előző példában az egyetlen útvonal nagyon egyszerű. Nem ad nekünk sok értéket, mivel már képesek voltunk a Home komponens megjelenítésére az útválasztó bevonása nélkül.

a React Router teljesítménye akkor jön be, amikor több útvonalat használunk annak meghatározására, hogy melyik komponensnek kell megjelenítenie az aktuálisan aktív útvonal alapján:

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

minden <Route> megjeleníti a megfelelő összetevőt, amikor az elérési útja megegyezik az URL-lel. E három komponens közül csak az egyik jelenik meg a 'root' – ban egy adott időpontban. Ezzel a stratégiával egyszer csatlakoztatjuk az útválasztót a Dom 'root' – hoz, majd az útválasztó az útvonalváltozásokkal ki-be cseréli az összetevőket.

azt is érdemes megjegyezni, hogy az útválasztó útvonalakat vált anélkül, hogy kéréseket küldene a szervernek, ezért képzelje el, hogy minden összetevő egy teljesen új oldal lehet.

újrafelhasználható elrendezés

kezdjük látni a szerény kezdetei egyetlen oldal alkalmazás. Ez azonban még mindig nem oldja meg a valós problémákat. Persze, a három összetevőt teljes HTML oldalakká építhetjük, de mi a helyzet a kód újrafelhasználásával? Valószínű, hogy ez a három összetevő közös eszközökkel rendelkezik, mint például a fejléc és az oldalsáv, tehát hogyan akadályozhatjuk meg a HTML ismétlését az egyes összetevőkben?

képzeljük el, hogy egy webalkalmazást építünk, amely hasonlított erre a makettre:

egy egyszerű weboldal makett.

amikor elkezd gondolkodni arról, hogy ezt a makettet hogyan lehet újrafelhasználható szakaszokra bontani, előfordulhat, hogy ez az ötlet jön létre:

hogyan bonthatja fel az egyszerű webes makettet szakaszokra.

a fészkelhető alkatrészekre és elrendezésekre való gondolkodás lehetővé teszi számunkra, hogy újrafelhasználható alkatrészeket hozzunk létre.

hirtelen a művészeti osztály tudatja Önnel, hogy az alkalmazásnak szüksége van egy oldalra a widgetek kereséséhez, amely hasonlít a felhasználók keresésére szolgáló oldalra. Mivel a felhasználói lista és a Widget lista egyaránt ugyanazt a “megjelenést” igényli a keresési oldalukhoz, az ötlet, hogy a keresési elrendezés külön komponensként legyen, még értelmesebb:

keressen widgeteket most, a felhasználók helyett, de a szülő szakaszok változatlanok maradnak.

a keresési elrendezés most már mindenféle keresési oldal szülő sablonja lehet. Míg egyes oldalak keresési elrendezést igényelhetnek, mások közvetlenül használhatják a fő elrendezést anélkül:

az elrendezés leválasztva.

ez egy általános stratégia, és ha bármilyen sablonrendszert használtál, akkor valószínűleg valami nagyon hasonlót csináltál. Most dolgozzunk a HTML-en. Kezdeni, statikus HTML-t fogunk csinálni a JavaScript figyelembevétele nélkül:

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

ne feledje, hogy a 'root' elem mindig jelen lesz, mivel ez az egyetlen elem, amellyel a kezdeti HTML törzs rendelkezik a JavaScript indítása előtt. A “gyökér” szó megfelelő, mert a teljes React alkalmazásunk hozzá fog férni. De nincs “helyes név” vagy konvenció annak, amit hívsz. A “root” – ot választottam, ezért továbbra is használni fogjuk a példákban. Csak vigyázzon, hogy a közvetlenül a <body> elemre történő szerelés nagyon nem ajánlott.

a statikus HTML létrehozása után alakítsa át React komponensekké:

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

ne zavarja túlságosan az, amit “elrendezés” vs “komponens” – nek hívok. Mindhárom komponens React. Csak úgy döntök, hogy kettőt “elrendezésnek” nevezek, mivel ezt a szerepet töltik be.

végül “beágyazott útvonalakat” fogunk használni a UserList SearchLayoutbelsejébe, majd a MainLayout belsejébe. De először vegye figyelembe, hogy amikor a UserList a SearchLayout szülőbe kerül, a szülő a this.props.children segítségével határozza meg a helyét. Minden komponensnek this.props.children kelléke van, de csak akkor, ha az összetevők be vannak ágyazva, a szülő komponens automatikusan kitölti ezt a támaszt a React által. Azoknál az összetevőknél, amelyek nem szülőösszetevők, a this.props.childrenértéke null lesz.

beágyazott útvonalak

tehát hogyan tudjuk ezeket az összetevőket fészkelni? Az útválasztó megteszi helyettünk, amikor útvonalakat fészkelünk:

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

az összetevők a router útvonalainak beágyazásának megfelelően lesznek beágyazva. Amikor a felhasználó meglátogatja a /users útvonalat, a React Router a UserList összetevőt a SearchLayout – be, majd mindkettőt a MainLayout – be helyezi. A /users látogatás végeredménye a 'root'belsejében elhelyezett három beágyazott összetevő lesz.

figyeljük meg, hogy nincs olyan szabály, amikor a felhasználó meglátogatja a Kezdőlap elérési útját (/), vagy keresgélni szeretne a widgetekben. Ezeket az egyszerűség kedvéért kihagyták, de tegyük be őket az új útválasztóval:

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

valószínűleg már észrevette, hogy a JSX az XML szabályokat követi abban az értelemben, hogy a Route komponens vagy egy címkeként írható: <Route />vagy kettő: <Route>...</Route>. Ez igaz az összes JSX-re, beleértve az egyéni komponenseket és a normál Dom csomópontokat. Például a <div /> érvényes JSX, és <div></div> – re konvertálódik, amikor megjelenik.

a rövidség kedvéért képzelje el, hogy a WidgetListhasonlít a UserList – ra.

mivel a <Route component={SearchLayout}> – nek két gyermekútvonala van, a felhasználó meglátogathatja a /users vagy a /widgets – et, és a megfelelő <Route> betölti a megfelelő komponenseket a SearchLayout komponensbe.

figyeld meg azt is, hogy a Home komponens hogyan kerül közvetlenül a MainLayout belsejébe anélkül, hogy SearchLayout részt venne benne — a <Route>s beágyazása miatt. Valószínűleg el tudod képzelni, hogy az útvonalak átrendezésével könnyű átrendezni az elrendezések és az összetevők egymásba ágyazását.

IndexRoutes

a React Router nagyon kifejező, és gyakran több módon is megteheti ugyanazt. Például írhattuk volna a fenti útválasztót is:

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

annak ellenére, hogy a különböző megjelenés, mindkettő működik pontosan ugyanúgy.

választható Útvonalattribútumok

néha az <Route> – nek lesz component attribútuma path nélkül, mint a SearchLayout útvonalon felülről. Más esetekben szükség lehet egy <Route> – re path – vel és component – val. Hogy miért, kezdjük ezzel a példával:

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

a /product része a path ismétlődő. Az ismétlést úgy távolíthatjuk el, hogy mindhárom útvonalat egy újba csomagoljuk <Route>:

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

a React Router ismét kifejezőképességét mutatja. Kvíz: észrevetted a problémát mindkét megoldással? Jelenleg nincs szabályunk arra, hogy a felhasználó mikor látogatja meg a /product elérési utat.

ennek kijavításához hozzáadhatunk egy IndexRoute:

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

a <Link> nem <a>

használata az útvonalak horgonyainak létrehozásakor a <Link to=""> értéket kell használnia a <a href="">helyett. Ne aggódjon, ha a <Link> összetevőt használja, a React Router végül egy közönséges horgonyt ad a DOM-ban. A <Link> használata azonban szükséges ahhoz, hogy a React Router elvégezze az útválasztási varázsát.

adjunk hozzá néhány linket (horgonyt) a 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> ); }});

a <Link> komponensek attribútumai átkerülnek az általuk létrehozott horgonyhoz. Tehát ez a JSX:

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

ez lesz a DOM-ban:

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

ha létre kell hoznia egy horgonyt a nem útválasztó útvonalakhoz, például egy külső webhelyhez, akkor a szokásos módon használjon normál horgonycímkéket. További információkért lásd az IndexRoute és a Link dokumentációját.

aktív linkek

a <Link> komponens hűvös tulajdonsága, hogy képes tudni, mikor aktív:

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

ha a felhasználó a /users útvonalon van, az útválasztó megkeresi a <Link> – vel készített megfelelő horgonyokat, és átkapcsolja a active osztályukat. További információ erről a funkcióról.

böngésző előzmények

a félreértések elkerülése érdekében eddig kihagytam egy fontos részletet. A <Router> – nak tudnia kell, hogy melyik előzménykövetési stratégiát használja. A React Router docs a browserHistory-t ajánlja, amely a következőképpen valósul meg:

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

a React Router korábbi verzióiban a history attribútum nem volt kötelező, Az alapértelmezett a hashHistory használata volt. Ahogy a neve is sugallja, egy # hash jelet használt az URL-ben a front-end SPA-stílusú útválasztás kezeléséhez, hasonlóan ahhoz, amit elvárhat egy gerinctől.js router.

hashHistory esetén az URL-ek így fognak kinézni:

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

mi van azokkal a csúnya lekérdezési karakterláncokkal?

a browserHistory megvalósításakor az útvonalak organikusabbnak tűnnek:

  • example.com
  • example.com/users
  • példa.com / widgetek

van egy figyelmeztetés, bár a szerveren, ha browserHistory használják a front-end. Ha a felhasználó example.com címen kezdi meg látogatását, majd /users és /widgets helyre navigál, a React Router a várakozásoknak megfelelően kezeli ezt a forgatókönyvet. Ha azonban a felhasználó a example.com/widgets beírásával kezdi meg látogatását közvetlenül a böngészőbe, vagy ha example.com/widgets – re frissül, akkor a böngészőnek legalább egy kérést kell benyújtania a szerverhez /widgets. Ha azonban nincs szerver oldali útválasztó, ez a 404:

óvatosan az URL-ekkel. Szüksége lesz egy szerver oldali útválasztóra.

a 404-es probléma kiszolgálóról történő megoldásához a React Router helyettesítő karakterű útválasztót javasol a szerver oldalon. Ezzel a stratégiával, függetlenül attól, hogy milyen szerveroldali útvonalat hívnak, a kiszolgálónak mindig ugyanazt a HTML fájlt kell kiszolgálnia. Ezután, ha a felhasználó közvetlenül a example.com/widgets – nél indul, annak ellenére, hogy ugyanazt a HTML fájlt adja vissza, a React Router elég okos ahhoz, hogy betöltse a megfelelő összetevőt.

a felhasználó nem fog észrevenni semmi furcsát, de aggályai lehetnek azzal kapcsolatban, hogy mindig ugyanazt a HTML fájlt szolgálja-e ki. Kódpéldákban, ez a sorozat továbbra is a “helyettesítő útválasztó” stratégiát fogja használni, de rajtad múlik, hogy a szerveroldali útválasztást tetszés szerint kezelje-e.

használható-e a React Router mind szerver, mind kliens oldalon izomorf módon? Persze, hogy lehet, de ez túlmutat az oktatóanyag keretein.

átirányítás browserHistory

a browserHistory objektum egyke, így bármelyik fájlba beillesztheti. Ha manuálisan kell átirányítania a felhasználót bármelyik kódjában, használhatja a push módszert erre:

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

útvonal-illesztés

a React router a többi útválasztóhoz hasonlóan kezeli az útvonal-illesztést:

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

ez az útvonal akkor egyezik meg, ha a Felhasználó bármilyen users/ – vel kezdődő útvonalat meglátogat, és utána bármilyen értékkel rendelkezik. Ez megegyezik a /users/1, /users/143 vagy akár /users/abc értékkel (amelyet saját magának kell érvényesítenie).

a React Router a :userIdértékét adja át támaszként a UserProfile – nek. Ez a kellékek elérhető this.props.params.userId belül UserProfile.

Router Demo

ezen a ponton elegendő kódunk van a bemutató megjelenítéséhez.

lásd Brad Westfall (@bradwestfall) Pen React-Router demóját a CodePen oldalon.

ha a példában néhány útvonalra kattintott, észreveheti, hogy a böngésző vissza-és előre gombjai működnek az útválasztóval. Ez az egyik fő oka ezeknek a history stratégiáknak. Ne feledje továbbá, hogy minden meglátogatott útvonalon nincs kérés a szerverre, kivéve a legelső, hogy megkapja a kezdeti HTML-t. Hát nem király?

ES6

CodePen példánkban a React, ReactDOM és ReactRouter globális változók egy CDN-ből. A ReactRouter objektum belsejében mindenféle dolog van, amire szükségünk van, például a Router és a Route komponensek. Tehát használhatnánk ReactRouter mint ez:

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

itt előtagot kell adnunk az összes útválasztó-összetevőnknek a ReactRouter szülőobjektummal. Vagy használhatnánk az ES6 új destrukturáló szintaxisát:

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

ez” kivonja ” a ReactRouter részeit normál változókká, így közvetlenül hozzáférhetünk hozzájuk.

mostantól kezdve a sorozat példái számos ES6 szintaxist fognak használni, beleértve a destrukturálást, a spread operátort, az importot/exportot és talán másokat is. Lesz egy rövid magyarázat minden új szintaxis, ahogy azok megjelennek, és a GitHub repo, hogy jön ez a sorozat is sok ES6 magyarázatok.

a webpack és a Babel csomagolása

mint korábban említettük, ez a sorozat GitHub repóval érkezik, így kísérletezhet a kóddal. Mivel ez hasonlít a hozzávaló egy valós SPA, akkor használja eszközök, mint a webpack és Babel.

  • a webpack több JavaScript fájlt köt össze egy fájlba a böngésző számára.
  • a Babel átalakítja az ES6 (ES2015) kódot ES5-re, mivel a legtöbb böngésző még nem érti az összes ES6-ot. Ahogy ez a cikk elöregszik, a böngészők támogatják az ES6-ot, és a Babel nem feltétlenül szükséges.

ha még nem túl kényelmes ezeket az eszközöket használni, ne aggódjon, a példakódban már minden be van állítva, így a reakcióra összpontosíthat. De győződjön meg róla, hogy vizsgálja felül a példa kódot README.md fájl további munkafolyamat-dokumentációhoz.

legyen óvatos az elavult szintaxissal kapcsolatban

ha a Google-ban információt keres a React routerről, akkor a sok cikk vagy StackOverflow oldal egyikére kerülhet, amelyeket a React Router 1.0 előtti kiadásában írtak. Sok funkciók a pre-1.0 kiadás elavult most. Itt egy rövid lista:

  • <Route name="" /> elavult. Használja helyette a <Route path="" /> értéket.
  • <Route handler="" /> elavult. Használja helyette a <Route component="" /> parancsot.
  • <NotFoundRoute /> elavult. Lásd alternatív
  • <RouteHandler /> elavult.
  • willTransitionTo elavult. Lásd onEnter
  • willTransitionFrom elavult. Lásd onLeave
  • a”helyeket” mostantól “történeteknek”nevezzük.

lásd a teljes listát 1.0.0 és 2.0.0

összefoglaló

a React routerben még mindig vannak olyan funkciók, amelyek nem voltak megjelenítve, ezért mindenképpen nézd meg az API dokumentumokat. Az alkotók a React Router is létrehozott egy lépésről-lépésre bemutató React Router, valamint a pénztár ezt reagálni.js Conf videó arról, hogyan React Router jött létre.

Külön köszönet Lynn Fishernek a @ lynnandtonic alkotásért

cikksorozat:

  1. React Router (Ön itt van!)
  2. Konténer Alkatrészek
  3. Redux

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.