Levelování s React: React Router

tento tutoriál je první ze třídílné série na React od Brad Westfall. Když mi to Brad hodil, poukázal na to, že existuje velké množství tutoriálů, jak začít v React, ale ne tolik o tom, kam jít odtamtud. Pokud jste zcela nový reagovat, doporučuji sledovat toto úvodní video. Tato série navazuje tam, kde končí základy.

řada článků:

  1. React Router (jste zde!)
  2. Container Components
  3. Redux

Varování! Tento článek byl napsán pre-React Router 4, který se stal standardnější volbou pro směrování v React. K dispozici je nový článek pokrývající React Router 4 Zde byste si určitě měli přečíst.

Když jsem byl nejprve učí, našla jsem hodně začátečník průvodce (tj. 1, 2, 3, 4), která ukázala, jak se jednotlivé komponenty a vykreslit je do DOM. Odvedli skvělou práci při výuce základů, jako jsou JSX a rekvizity – ale snažil jsem se přijít na to, jak React funguje ve větším obraze-jako aplikace v reálném světě (SPA). Vzhledem k tomu, že tato série pokrývá spoustu materiálu, nepokryje absolutní koncepty pro začátečníky. Místo toho začne s předpokladem, že již rozumíte tomu, jak vytvořit a vykreslit alespoň jednu komponentu.

za to, co stojí za to, zde jsou některé další skvělé průvodce, které se zaměřují na začátečníky:

  • reaguj.js a jak to zapadá do všeho ostatního?
  • Rethinking (Industry) Best Practices
  • React.JS Úvod pro lidi, kteří vědí jen tolik jQuery se dostat do

kód série

tato série také přichází s nějakým kódem na hraní na GitHub. V celé sérii budeme budovat základní lázně zaměřené na uživatele a widgety.

Chcete-li udržet věci jednoduché a stručné, příklady v této sérii začnou za předpokladu, že React a React Router jsou načteny z CDN. Takže v bezprostředních příkladech níže neuvidíte require() nebo import. Ke konci tohoto tutoriálu však představíme Webpack a Babel pro průvodce GitHub. V tu chvíli je to všechno ES6!

React-Router

React není rámec, je to Knihovna. Proto neřeší všechny potřeby aplikace. Dělá skvělou práci při vytváření komponent a poskytování systému pro správu státu, ale vytvoření složitějšího SPA bude vyžadovat podpůrné obsazení. První, na kterou se podíváme, je React Router.

pokud jste dříve používali jakýkoli front-end router, mnoho z těchto konceptů bude známé. Ale na rozdíl od jiných routerů, které jsem použil dříve, React Router používá JSX, což může zpočátku vypadat trochu divně.

Jako základní nátěr, to je to, co to je render jediného komponentu:

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

Zde je návod, jak Home složka by být vykreslen s React Router:

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

Všimněte si, že <Router> a <Route> jsou dvě různé věci. Jsou to technicky reagující komponenty, ale ve skutečnosti nevytvářejí DOM sami. I když to může vypadat jako <Router> sám je vykreslen na 'root', jsme vlastně jen definování pravidel o tom, jak naše aplikace funguje. Pohyb vpřed, tento koncept uvidíte často: komponenty někdy neexistují proto, aby samy vytvořily DOM, ale aby koordinovaly další komponenty, které to dělají.

v příkladu <Route> definuje pravidlo, kde návštěva domovské stránky / vykreslí komponentu Home do 'root'.

více tras

v předchozím příkladu je jedna trasa velmi jednoduchá. Nedává nám to velkou hodnotu, protože jsme již měli možnost vykreslit komponentu Home bez zapojení routeru.

Reagovat Router je moc přichází, když používáme více tras definovat, která komponenta by měla poskytnout na základě které cesta je v současné době aktivní:

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

Každý <Route> činí jeho příslušné součásti při cestě odpovídá URL. Pouze jedna z těchto tří komponent bude v daném okamžiku vykreslena do 'root'. S touto strategií připojíme směrovač k DOM 'root' jednou, pak komponenty routeru zaměníme dovnitř a ven se změnami trasy.

je také třeba poznamenat, že router přepne trasy bez požadavků na server, takže si představte, že každá komponenta může být zcela nová stránka.

znovu použitelné rozvržení

začínáme vidět skromné začátky jednostránkové aplikace. Stále však neřeší skutečné problémy. Jistě, mohli bychom vytvořit tři komponenty, aby byly plné HTML stránky, ale co opětovné použití kódu? Je pravděpodobné, že tyto tři komponenty sdílejí společná aktiva, jako je záhlaví a postranní panel, takže jak zabráníme opakování HTML v každé komponentě?

představme si, že jsme budovali webovou aplikaci, která se podobala této maketě:

jednoduchý web maketa.

Když začnete přemýšlet o tom, jak tento model může být rozdělen do re-použitelné části, ty by mohly skončit s touto myšlenkou:

Jak jste se mohli rozejít jednoduchý web mockup do sekcí.

myšlení z hlediska nestabilních komponent a rozvržení nám umožní vytvářet opakovaně použitelné součásti.

najednou vám oddělení umění oznámí, že aplikace potřebuje stránku pro vyhledávání widgetů, která se podobá stránce pro vyhledávání uživatelů. S Seznam Uživatelů a Seznam Widgetu oba vyžadují stejný „vzhled“ pro své vyhledávací stránku, nápad mít Vyhledávání Rozložení jako samostatná složka dává ještě větší smysl:

Hledat widget nyní, v místě uživatele, ale mateřské oddíly zůstávají stejné.

rozvržení vyhledávání může být nadřazenou šablonou pro všechny druhy vyhledávacích stránek. A zatímco některé stránky mohou potřebovat rozvržení vyhledávání, jiné mohou přímo používat Hlavní rozvržení bez něj:

rozložení oddělené.

Toto je běžná strategie a pokud jste použili jakýkoli šablonovací systém, pravděpodobně jste udělali něco velmi podobného. Nyní pojďme pracovat na HTML. Chcete-li začít, uděláme statické HTML bez zvážení JavaScriptu:

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

nezapomeňte, že prvek 'root' bude vždy přítomen, protože je to jediný prvek, který má počáteční tělo HTML před spuštěním JavaScriptu. Slovo „root“ je vhodné, protože se k němu připojí celá naše aplikace React. Ale neexistuje žádné „správné jméno“ nebo konvence k tomu, čemu říkáte. Vybral jsem „root“, takže jej budeme i nadále používat v příkladech. Jen si dejte pozor, že montáž přímo na prvek <body> je velmi odrazována.

po vytvoření statického HTML jej převeďte na komponenty 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> ); }});

nenechte se příliš rozptylovat mezi tím, co nazývám “ Layout „vs “ Component“. Všechny tři jsou složky React. Jen jsem se rozhodl nazvat dva z nich „rozvržení“, protože to je role, kterou vykonávají.

nakonec použijeme „vnořené trasy“ k umístění UserList uvnitř SearchLayout, pak uvnitř MainLayout. Nejprve si však všimněte, že když je UserList umístěn uvnitř svého rodiče SearchLayout, rodič použije this.props.children k určení jeho umístění. Všechny komponenty mají this.props.children jako rekvizita, ale to je pouze tehdy, když komponenty jsou vnořené, že mateřská komponenta dostane tato rekvizita vyplněna automaticky Reagovat. Pro komponenty, které nejsou nadřazenými komponenty, this.props.children bude null.

vnořené trasy

jak tedy dostaneme tyto komponenty do hnízda? Router to dělá za nás, když hnízdíme trasy:

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

komponenty budou vnořeny v souladu s tím, jak router hnízdí své trasy. Když uživatel navštíví trasu /users, React Router umístí komponentu UserList dovnitř SearchLayout a poté obě uvnitř MainLayout. Konečným výsledkem návštěvy /users budou tři vnořené komponenty umístěné uvnitř 'root'.

Všimněte si, že nemáme pravidlo, kdy uživatel navštíví cestu domovské stránky (/) nebo chce hledat widgety. Ty byly vynechány pro jednoduchost, ale pojďme je dát do nového routeru:

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

pravděpodobně jste si všimli, že JSX dodržuje pravidla XML v tom smyslu, že komponenta Route může být zapsána jako jedna značka: <Route /> nebo dvě: <Route>...</Route>. To platí pro všechny JSX včetně vlastních komponent a normálních Dom uzlů. Například <div /> je platný JSX a při vykreslení převede na <div></div>.

pro stručnost si představte, že WidgetList se podobá UserList.

vzhledem k tomu, že <Route component={SearchLayout}> má nyní dvě podřízené trasy, může uživatel navštívit /users nebo /widgets a odpovídající <Route> načte své příslušné komponenty uvnitř komponenty SearchLayout.

všimněte si také, jak bude komponenta Home umístěna přímo uvnitř MainLayout, aniž by byla zapojena SearchLayout – kvůli tomu, jak jsou vnořeny <Route>s. Pravděpodobně si dokážete představit, že je snadné uspořádat rozložení a komponenty vnořené přeskupením tras.

IndexRoutes

React Router je velmi expresivní a často existuje více než jeden způsob, jak udělat totéž. Například jsme mohli také napsat výše uvedený router takto:

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

přes svůj odlišný vzhled, oba pracují přesně stejným způsobem.

Volitelné atributy trasy

někdy <Route> bude mít atribut component bez path, jako v SearchLayout trase shora. Jindy může být nutné mít <Route> s path a ne component. Chcete-li zjistit, proč, začněme s tímto příkladem:

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

/product část path se opakuje. Opakování můžeme odstranit zabalením všech tří tras do nového <Route>:

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

React Router opět ukazuje svou expresivitu. Kvíz: všimli jste si problému s oběma řešeními? V tuto chvíli nemáme žádná pravidla pro to, kdy uživatel navštíví cestu /product.

to napravit, můžeme přidat IndexRoute:

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

Použití <Link> <a>

Při vytváření kotvy pro své cesty, budete muset použít <Link to=""> místo <a href="">. Nebojte se, když používáte komponentu <Link>, React Router vám nakonec poskytne obyčejnou kotvu v DOM. Použití <Link> je však nezbytné, aby React Router provedl některé ze svých směrovacích kouzel.

přidejme nějaký odkaz (kotvy) k našemu 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> ); }});

atributy na komponentách <Link> budou předány do kotvy, kterou vytvoří. Takže tohle JSX:

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

stane se to v DOM:

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

pokud potřebujete vytvořit kotvu pro cesty mimo směrovač, například externí web, použijte normální kotevní značky jako obvykle. Pro více informací, viz dokumentace pro IndexRoute a odkaz.

aktivní odkazy

skvělou vlastností komponenty <Link> je její schopnost vědět, kdy je aktivní:

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

pokud je uživatel na cestě /users, router vyhledá odpovídající kotvy, které byly vytvořeny pomocí <Link>, a přepne jejich třídu active. Více informací o této funkci.

historie prohlížeče

abych předešel nejasnostem, vynechal jsem až dosud důležitý detail. <Router> potřebuje vědět, kterou strategii sledování historie použít. Reagovat Router docs doporučit browserHistory který je realizován následovně:

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

V předchozích verzích Reagovat Router, history atribut není vyžadován a výchozí bylo použít hashHistory. Jak již název napovídá, používá # hash znak v URL pro správu front-end SPA stylu směrování, podobné tomu, co byste mohli očekávat od páteře.JS router.

S hashHistory, Url bude vypadat takto:

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

Co se děje s těmito ošklivé řetězce dotazu?

Když browserHistory je realizován cesty vypadat více ekologická:

  • example.com
  • example.com/users
  • příklad.com / widgets

na Serveru je však upozornění, když je na front-endu použito browserHistory. Pokud uživatel zahájí svou návštěvu na example.com a poté přejde na /users a /widgets, React Router zpracovává tento scénář podle očekávání. Nicméně, pokud uživatel začne svou návštěvu zadáním example.com/widgets přímo do prohlížeče, nebo jestli budou aktualizovat na example.com/widgets, pak prohlížeč musí alespoň jeden požadavek na server /widgets. Pokud však není směrovač na straně serveru, přinese to 404:

opatrně s adresami URL. Budete potřebovat směrovač na straně serveru.

Chcete-li vyřešit problém 404 ze serveru, React Router doporučuje zástupný směrovač na straně serveru. S touto strategií, bez ohledu na to, jaká trasa na straně serveru se nazývá, by server měl vždy sloužit stejnému souboru HTML. Pokud uživatel spustí přímo na example.com/widgets, i když je vrácen stejný soubor HTML, React Router je dostatečně chytrý, aby načetl správnou komponentu.

uživatel si nevšimne nic divného, ale můžete mít obavy, že budete vždy obsluhovat stejný soubor HTML. V příkladech kódu bude tato řada i nadále používat strategii“ wildcard router“, ale je na vás, abyste zvládli směrování na straně serveru způsobem, který uznáte za vhodný.

lze React Router použít na straně serveru i na straně klienta izomorfním způsobem? Jistě, že může, ale to je daleko nad rámec tohoto tutoriálu.

přesměrování pomocí browserHistory

objekt browserHistory je singleton, takže jej můžete zahrnout do libovolného souboru. Pokud potřebujete ručně přesměrovat uživatele v libovolném kódu, můžete k tomu použít metodu push :

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

Trasy Odpovídající

Reagovat router zpracovává trasy odpovídající podobně jako jiné routery:

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

Tato trasa bude odpovídat, když uživatel navštíví jakoukoli cestu, která začíná s users/ a má nějakou hodnotu později. Bude odpovídat /users/1, /users/143 nebo dokonce /users/abc (které budete muset ověřit sami).

React Router předá hodnotu pro :userId jako podpěru UserProfile. Tyto rekvizity jsou přístupné jako this.props.params.userId uvnitř UserProfile.

Router Demo

v tomto okamžiku máme dostatek kódu pro zobrazení demo.

viz pero React-Router Demo Brad Westfall (@bradwestfall) na CodePen.

pokud jste v příkladu klikli na několik tras, můžete si všimnout, že tlačítka zpět a vpřed prohlížeče pracují se směrovačem. To je jeden z hlavních důvodů, proč tyto history strategie existují. Mějte také na paměti, že při každé navštívené trase se na server nevyskytují žádné požadavky, s výjimkou prvního, který získá počáteční HTML. Není to super?

ES6

v našem příkladu CodePen jsou React, ReactDOM a ReactRouter globální proměnné z CDN. Uvnitř objektu ReactRouter jsou všechny druhy věcí, které potřebujeme, jako jsou komponenty Router a Route. Takže můžeme použít ReactRouter takto:

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

zde musíme všechny komponenty routeru prefixovat jejich nadřazeným objektem ReactRouter. Nebo můžeme použít ES6 nové destructuring syntaxi jako je tato:

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

Tento „výtažky“ části ReactRouter do normální proměnné, tak můžeme k nim přistupovat přímo.

od této chvíle budou příklady v této sérii používat různé syntaxe ES6 včetně destrukce, operátora šíření, dovozu/vývozu a možná i dalších. Bude stručné vysvětlení každé nové syntaxe, jak se objeví, a repo GitHub, které přichází s touto sérií, má také spoustu vysvětlení ES6.

sdružování s webpack a Babel

jak bylo uvedeno výše, tato série je dodáván s GitHub repo, takže můžete experimentovat s kódem. Vzhledem k tomu, že se bude podobat tvorbě lázní v reálném světě, bude používat nástroje jako webpack a Babel.

  • webpack svazky více souborů JavaScript do jednoho souboru pro prohlížeč.
  • Babel převede kód ES6 (ES2015) na ES5, protože většina prohlížečů ještě nerozumí všem ES6. Jak tento článek stárne, prohlížeče budou podporovat ES6 a Babel nemusí být potřeba.

Pokud nejste příliš pohodlné používání těchto nástrojů ještě, nebojte se, příklad kód má vše nastavení již, takže se můžete soustředit na reagovat. Nezapomeňte si však přečíst ukázkový kód README.md Soubor pro další dokumentaci pracovního postupu.

Být Opatrní, O tom, Zastaralé Syntaxe

Vyhledávání Google pro info Reagovat na Routeru může přistát na jednom z mnoha článků nebo StackOverflow stránky, které byly napsány, když Reagují Router byl v jeho pre 1.0 release. Mnoho funkcí z pre-1.0 vydání jsou nyní zastaralé. Zde je krátký seznam:

  • <Route name="" /> je zastaralý. Místo toho použijte <Route path="" />.
  • <Route handler="" /> je zastaralé. Místo toho použijte <Route component="" />.
  • <NotFoundRoute /> je zastaralé. Viz alternativa
  • <RouteHandler /> je zastaralá.
  • willTransitionTo je zastaralé. Viz onEnter
  • willTransitionFrom je zastaralý. Viz onLeave
  • „místa“ se nyní nazývají „historie“.

Viz úplný seznam 1.0.0 a 2.0.0

shrnutí

v React routeru jsou stále další funkce, které nebyly zobrazeny, takže se podívejte na dokumenty API. Tvůrci React routeru také vytvořili podrobný návod pro React Router a také pokladnu tohoto React.js Conf Video o tom, jak byl vytvořen React Router.

Zvláštní poděkování Lynn Fisher pro kresbu @lynnandtonic

Článek Série:

  1. Reagovat Router (Ty jsou tady!)
  2. Container Components
  3. Redux

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.