Nivelar com Reat: Reat Router

este tutorial é o primeiro de uma série de três partes sobre Reat by Brad Westfall. Quando Brad me apresentou isso, ele apontou que há uma boa quantidade de tutoriais em começar a reagir, mas não tanto sobre para onde ir a partir daí. Se você é novinho em folha para reagir, eu recomendo assistir este vídeo de introdução. Esta série começa onde o básico termina.Série de artigos:

  1. reate Router (você está aqui!)
  2. Componentes Dos Contentores
  3. Redux

Aviso! Este artigo foi escrito roteador pre-React 4, que se tornou uma escolha mais padrão para roteamento em Reat. Há um novo artigo cobrindo Reat Router 4 Aqui você deve definitivamente ler.

quando eu estava aprendendo pela primeira vez, eu encontrei muitos guias iniciantes (ou seja, 1, 2, 3, 4) que mostravam como fazer componentes individuais e rendê-los ao DOM. Eles fizeram um bom trabalho de ensinar o básico como JSX e adereços, mas eu lutei para descobrir como a reação funciona no quadro maior – como uma aplicação de Página Única do mundo real (SPA). Uma vez que esta série cobre um monte de material, não irá cobrir os conceitos de principiante absoluto. Em vez disso, ele vai começar com a suposição de que você já entende como criar e renderizar pelo menos um componente.Para que conste, Aqui estão alguns outros grandes guias que visam principiantes.:

  • reaja.js e como se encaixa com tudo o resto?
  • Rethinking (Industry) Best Practices
  • React.js Introduction For People Who Know Just Enough jQuery To Get By

Series Code

this series also comes with some code to play with at GitHub. Ao longo da série, vamos construir um SPA básico focado em torno de usuários e widgets.

para manter as coisas simples e breves, os exemplos desta série começarão assumindo que roteador reate e reate são recuperados a partir de uma CDN. Então você não verá require() ou import nos exemplos imediatos abaixo. No final deste tutorial, no entanto, vamos apresentar Webpack e Babel para os guias GitHub. Nesse momento, é tudo ES6!

Reat-Router

Reat isn’t a framework, it’s a library. Portanto, não resolve todas as necessidades de uma aplicação. Ele faz um grande trabalho na criação de componentes e fornecer um sistema de gestão do estado, mas a criação de um SPA mais complexo vai exigir um elenco de apoio. O primeiro que vamos ver é Reat Router.

se você já usou qualquer roteador front-end Antes, muitos destes conceitos serão familiares. Mas ao contrário de qualquer outro router que já usei antes, Reat Router usa JSX, o que pode parecer um pouco estranho no início.Como iniciador, é assim que se torna um único componente:

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

aqui está como o componente Home seria renderizado com Router React:

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

Note que <Router> e <Route> são duas coisas diferentes. Eles são componentes de reação técnica, mas eles realmente não criam DOM eles mesmos. Embora possa parecer que o <Router> em si está sendo renderizado para o 'root', estamos na verdade apenas definindo regras sobre como a nossa aplicação funciona. Seguindo em frente, você verá este conceito muitas vezes: Componentes às vezes existem não para criar DOM em si, mas para coordenar outros componentes que o fazem.

no exemplo, o <Route> define uma regra onde visitar a página inicial / irá tornar o componente Home no 'root'.

múltiplas vias

no exemplo anterior, a única via é muito simples. Ele não nos dá muito valor, já que já tínhamos a capacidade de renderizar o componente Home sem que o roteador estivesse envolvido.

o poder do Router Reat vem quando usamos várias rotas para definir qual componente deve ser renderizado com base em qual caminho está atualmente ativo:

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

cada <Route> irá desenhar o seu componente respectivo quando a sua localização corresponder ao URL. Apenas um destes três componentes será renderizado para o 'root' em qualquer momento. Com esta estratégia, montamos o roteador para o DOM 'root' uma vez, em seguida, os componentes de troca do roteador para dentro e para fora com mudanças de rota.

também vale a pena notar que o roteador vai mudar de rotas sem fazer pedidos para o servidor, então imagine que cada componente poderia ser uma página totalmente nova.

Layout reutilizável

estamos começando a ver o início humilde de uma aplicação de uma única página. No entanto, ainda não resolve os problemas do mundo real. Claro, podemos construir os três componentes para serem páginas HTML completas, mas e a reutilização de código? É provável que estes três componentes compartilhem ativos comuns como um cabeçalho e barra lateral, então como evitamos repetição HTML em cada componente?Vamos imaginar que estávamos a construir uma aplicação web que se assemelhava a esta maquete.:

um simples modelo de website.

quando começar a pensar em como esta maquete pode ser dividida em secções reutilizáveis, poderá acabar com esta ideia:

como você pode quebrar a maquete web simples em seções.

pensar em termos de componentes e layouts nestáveis nos permitirá criar partes reutilizáveis.De repente, o departamento de arte permite-lhe saber que o aplicativo precisa de uma página para procurar widgets que se assemelha à página para procurar utilizadores. Com a lista de Usuários e lista de Widget ambos exigindo o mesmo “olhar” para a sua página de pesquisa, a idéia de ter Layout de pesquisa como um componente separado faz ainda mais sentido agora:

Procure por widgets agora, no lugar dos usuários, mas as seções-mãe permanecem as mesmas.

a disposição de pesquisa pode ser um modelo pai para todos os tipos de páginas de pesquisa agora. E enquanto algumas páginas podem precisar do Layout de pesquisa, outras podem usar diretamente o Layout principal sem ele:

um layout dissociado.

esta é uma estratégia comum e se você usou qualquer sistema de templação, você provavelmente fez algo muito semelhante. Agora vamos trabalhar no HTML. Para começar, vamos fazer HTML estático sem considerar 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>

lembre-se, o elemento 'root' estará sempre presente uma vez que é o único elemento que o corpo HTML inicial tem antes do JavaScript começar. A palavra “root” é apropriada porque toda a nossa aplicação React irá montar a ela. Mas não há” nome certo ” ou convenção para o que lhe chamas. Eu escolhi “root”, então vamos continuar a usá-lo através dos exemplos. Apenas tenha cuidado que a montagem diretamente para o elemento <body> é altamente desencorajado.

depois de criar o HTML estático, converta-o em componentes 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> ); }});

não te distraias muito com o que estou a chamar de “Layout” vs “componente”. Todos estes três são componentes de reacção. Só escolhi chamar a dois deles “Layouts”, já que é esse o papel que estão a desempenhar.

eventualmente usaremos “rotas aninhadas” para colocar UserList dentro de SearchLayout, depois dentro de MainLayout. Mas primeiro, observe que quando UserList é colocado dentro de seu pai SearchLayout , o pai vai usar this.props.children para determinar sua localização. Todos os componentes têm this.props.children como um adereço, mas só quando os componentes são aninhados é que o componente-mãe recebe este adereço preenchido automaticamente pela React. Para componentes que não são componentes-mãe, this.props.children será null.

rotas aninhadas

então como fazemos estes componentes para nidificar? O router faz isso por nós quando nidificamos rotas:

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

os componentes serão aninhados de acordo com a forma como o router insere as suas rotas. Quando o utilizador visitar a rota /users, o Router React colocará o componente UserList dentro de SearchLayout e então ambos dentro de MainLayout. O resultado final da visita /users serão os três componentes aninhados colocados dentro de 'root'.

Notice that we don’t have a rule for when the user visits the home page path (/) or wants to search widgets. Esses foram deixados de fora por simplicidade, mas vamos colocá-los com o novo roteador:

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

provavelmente já reparou que o JSX segue as regras XML no sentido de que o componente Route pode ser escrito como uma etiqueta: <Route /> ou duas: <Route>...</Route>. Isto é verdade para todos os JSX incluindo seus componentes personalizados e nós DOM normais. Por exemplo, <div /> é válido JSX e irá converter para <div></div> quando renderizado.

para a brevidade, basta imaginar WidgetList assemelha-se ao UserList.

uma vez que <Route component={SearchLayout}> tem duas vias infantis agora, o utilizador pode visitar /users ou /widgets e o correspondente <Route> irá carregar os seus respectivos componentes dentro do componente SearchLayout.

também, observe como o componente Home será colocado diretamente dentro de MainLayout sem SearchLayout estar envolvido-por causa de como os <Route>s são aninhados. Você provavelmente pode imaginar que é fácil reorganizar como layouts e componentes são aninhados, reorganizando as rotas.

IndexRoutes

React Router is very expressive and often there’s more than one way to do the same thing. Por exemplo, nós também poderíamos ter escrito o roteador acima como este:

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

apesar do seu aspecto diferente, ambos funcionam exactamente da mesma maneira.

atributos de rota facultativos

às vezes, <Route> terá um atributo component sem path, como na rota SearchLayout acima. Outras vezes, pode ser necessário ter um <Route> com um path e não component. Para ver porquê, vamos começar com este exemplo:

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

a porção /product da path é repetitiva. Podemos remover a repetição, embrulhando todas as três rotas em um novo <Route>:

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

mais uma vez, Reat Router mostra sua expressividade. Quiz: você notou o problema com ambas as soluções? No momento não temos regras para quando o usuário visita o caminho /product.

Para corrigir isso, podemos adicionar um IndexRoute:

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

Use <Link> não <a>

Quando a criação de âncoras para as suas rotas, você precisará usar <Link to=""> em vez de <a href="">. Não se preocupe, no entanto, ao usar o componente <Link>, Reat Router irá finalmente dar – lhe uma âncora comum no DOM. Usando <Link> embora seja necessário para Reat Router fazer parte de sua magia de roteamento.

vamos adicionar alguma ligação (âncoras) aos nossos 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> ); }});

os atributos dos componentes <Link> serão passados para a âncora que criam. Então este JSX:

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

tornar-se-á isto em DOM:

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

se você precisa criar uma âncora para caminhos não-roteadores, como um site externo, então use etiquetas de âncora normais como de costume. Para mais informações, consulte a documentação para IndexRoute e Link.

ligações activas

uma característica fixe do componente <Link> é a sua capacidade de saber quando está activo:

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

se o utilizador estiver no caminho /users, o router irá procurar âncoras correspondentes que foram feitas com <Link> e irá alternar a sua classe active. Veja mais sobre este recurso.

histórico do navegador

para evitar confusão, eu deixei de fora um detalhe importante até agora. O <Router> precisa saber qual estratégia de rastreamento de histórico usar. Reat Router docs recommend browserHistory which is implemented as follows:

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

em versões anteriores do router React, o atributo history não era necessário e o padrão era usar hashHistory. Como o nome sugere, ele usou um sinal de hash # no URL para gerenciar roteamento de estilo SPA front-end, semelhante ao que você pode esperar de uma espinha dorsal.router js.

com hashHistory, os URLs serão assim:

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

What’s up with those ugly query strings though?

Quando browserHistory é implementado, os caminhos olhar mais orgânica:

  • example.com
  • example.com/users
  • exemplo.com / widgets

há uma advertência no servidor quando browserHistory é usado no front-end. Se o usuário iniciar sua visita em example.com e, em seguida, navegar para /users e /widgets , Reat Router lida com este cenário como esperado. No entanto, se o usuário iniciar sua visita digitando example.com/widgets diretamente no navegador, ou se eles refrescarem em example.com/widgets, então o navegador deve fazer pelo menos um pedido ao servidor para /widgets. No entanto, se não existir um router do lado do servidor, este irá entregar um 404:

Cuidado com URLs. Vai precisar de um router do lado do servidor.

para resolver o problema 404 a partir do servidor, Reat Router recomenda um router wildcard no lado do servidor. Com esta estratégia, não importa qual rota do servidor é chamada, o servidor deve sempre servir o mesmo arquivo HTML. Então, se o usuário começa diretamente em example.com/widgets, mesmo que o mesmo arquivo HTML seja devolvido, Reat Router é inteligente o suficiente para carregar o componente correto.

o Usuário não vai notar nada estranho, mas você pode ter preocupações sobre sempre servir o mesmo arquivo HTML. Em exemplos de código, Esta série continuará a usar a estratégia do “router wildcard”, mas cabe a você lidar com o seu roteamento do lado do servidor de maneira que você considere adequada.

Can React Router be used on both server-side and client-side in an isomorphic way? Claro que pode, mas isso está muito além do escopo deste tutorial.

redirecione com browserHistory

o objeto browserHistory é um singleton para que você possa incluí-lo em qualquer um de seus arquivos. Se você precisar redirecionar manualmente o usuário em qualquer um de seu código, você pode usar o método push para fazê-lo:

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

Route Matching

React router handles route matching similarly to other routers:

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

esta rota corresponderá quando o usuário visitar qualquer caminho que comece com users/ e tenha qualquer valor depois. Irá corresponder a /users/1, /users/143, ou mesmo /users/abc (que terá de validar sozinho).

Reat Router will pass the value for :userId as a prop to the UserProfile. Este material é acessado como this.props.params.userId dentro UserProfile.

Router Demo

neste ponto, temos código suficiente para mostrar uma demo.

veja a demonstração do Pen Reat-Router por Brad Westfall (@bradwestfall) no CodePen.

se você clicou em algumas rotas no exemplo, você pode notar que os botões para trás e para a frente do navegador funcionam com o roteador. Esta é uma das principais razões pelas quais estas estratégias history existem. Além disso, tenha em mente que com cada rota que você visita, não há pedidos sendo feitos para o servidor, exceto o primeiro a obter o HTML inicial. Não é fixe?

ES6

In our CodePen example, React, ReactDOM, and ReactRouter are global variables from a CDN. Dentro do objeto ReactRouter estão todos os tipos de coisas que precisamos, como os componentes Router e Route. Assim poderíamos usar ReactRouter assim:

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

aqui, temos que prefixar todos os nossos componentes de roteador com seu objeto pai ReactRouter. Ou podemos usar a nova sintaxe de destruição da ES6 assim.:

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

esta” extrai ” partes de ReactRouter em variáveis normais para que possamos acessá-las diretamente.

a partir de agora, os exemplos desta série irão usar uma variedade de sintaxes ES6 incluindo destruição, o operador de propagação, importações / exportações, e talvez outros. Haverá uma breve explicação de cada nova sintaxe à medida que aparecem e o GitHub repo que vem com esta série também tem muitas explicações ES6.

em conjunto com webpack e Babel

como indicado antes, Esta série vem com um repo GitHub para que você possa experimentar com o código. Uma vez que vai se assemelhar aos ingredientes de um SPA do mundo real, ele vai usar ferramentas como webpack e Babel.

  • o webpack agrupa vários ficheiros JavaScript num ficheiro para o navegador.
  • Babel irá converter o código ES6 (ES2015) para ES5, uma vez que a maioria dos navegadores ainda não compreende todas as ES6. Como este artigo envelhece, navegadores irão apoiar ES6 e Babel pode não ser necessário.

se ainda não estiver muito confortável usando estas ferramentas, não se preocupe, o código de exemplo já tem tudo configurado para que você possa se concentrar em Reat. Mas certifique-se de rever o código de exemplo README.md ficheiro para a documentação adicional do fluxo de trabalho.

tenha cuidado com a sintaxe desactualizada

pesquisar no Google informações sobre o Router React pode colocá-lo em um dos muitos artigos ou páginas de StackOverflow que foram escritos quando Reat Router estava em sua versão pré-1.0. Muitas características do pré-1.0 lançamento está desactualizado agora. Aqui está uma pequena lista:

  • <Route name="" /> está desacreditado. Utilizar <Route path="" /> em vez disso.
  • <Route handler="" /> está desactualizado. Utilize <Route component="" /> em vez disso.
  • <NotFoundRoute /> está desactualizado. Ver alternativa
  • <RouteHandler /> está desactualizada.
  • willTransitionTo está desactualizado. Ver onEnter
  • willTransitionFrom está desactualizado. See onLeave
  • ” Locations “are now called”histories”.

ver a lista completa para 1.0.0 e 2.0.0

resumo

existem ainda mais características no roteador React que não foram mostrados, por isso certifique-se de verificar os documentos da API. Os criadores do router Reat também criaram um tutorial passo-a-passo para o router Reat e também checkout este Reat.js Conf Video on how React Router was created.

Agradecimentos especiais a Lynn Fisher pela obra de arte @lynnandtonic

série de artigos:

  1. reate Router (você está aqui!)
  2. Componentes Dos Contentores
  3. Redux

Deixe uma resposta

O seu endereço de email não será publicado.