前端技術 | react-router,去中心化式路由

1.靜態路由 vs. 動態路由

在Web前端開發中,咱們常常會須要處理頁面路由問題。習慣上,路由信息會在一個地方集中配置好,咱們能夠稱之爲「靜態路由」,或者叫「中心化式路由」。以react-router v3版本爲例,代碼相似下面這樣:前端

import { Router, Route, IndexRoute, browserHistory } from 'react-router'

const App = () => (
  <Router history={browserHistory}>
    <Route path="/" component={RootPage}>
      <IndexRoute component={HomePage} />
      <Route path="/users" component={UsersPage} />
    </Route>
  </Router>
)

render(<App />, document.getElementById('app'))
複製代碼

能夠看到,在程序的頂層組件上配置好了全部路由信息,並經過嵌套關係體現不一樣的層次。可是,react-router v4版本進行了革命性的改動,使之更加符合React的「組件化」思想,咱們能夠稱之爲「動態路由」,或者借用區塊鏈中的術語,稱之爲「去中心化路由」。用v4版本改寫後的代碼相似於下面這樣:react

import { BrowserRouter, Route } from 'react-router-dom'

const App = () => (
  <BrowserRouter>
    <RootPage />
  </BrowserRouter>
)

const RootPage = () => (
  <div>
    <Route path="/" exact component={HomePage} />
    <Route path="/users" component={UsersPage} />
  </div>
)

render(<App />, document.getElementById('app'))
複製代碼

能夠發現,路由的配置再也不是所有位於頂層組件中了,而是分散在不一樣的組件中,經過組件的嵌套關係來實現路由的層次。另外,和靜態路由事先定義好全部頁面不一樣,動態路由能夠在渲染時根據路徑匹配結果,動態決定渲染哪些組件,這樣就能夠充分實現頁面的複用,減小重複渲染。下面依次介紹react-router v4的相關組件。正則表達式

2.Router

react-router內部其實是利用了瀏覽器的history API,所以在v3版本中咱們須要在頂層的<Router>組件中傳入一個history屬性。在v4版本中爲咱們封裝了一個<BrowserRouter>組件,咱們須要把它包在全部組件的最外層:瀏覽器

import { BrowserRouter } from 'react-router-dom'
const App = () => (
  <BrowserRouter>
    ... ...
  </BrowserRouter>
)
複製代碼

另外還有一個<HashRouter>組件,是爲了兼容之前版本的瀏覽器,已經不推薦使用了。bash

3.路由匹配

路由匹配主要涉及兩個組件:<Route>和<Switch>,下面分別介紹。react-router

3.1 <Route>

<Route>組件包含3類屬性:匹配屬性、渲染方法、路由屬性app

3.1.1 匹配屬性

這些屬性是爲了設定url匹配規則。dom

(1) path:路由匹配正則表達式函數

舉例:工具

<Route path='/' />:匹配以/開頭的路徑,好比/,/login,/login/alice

<Route path='/login/:username' />:能夠匹配/login/alice,參數能夠經過props.match.params.username得到

(2) exact:精確匹配

舉例:

<Route path='/' exact />:只能精確匹配/,不能匹配/login

在v4版本里取消了<IndexRoute>組件,所以若是你但願在根路徑顯示某個頁面的話,能夠用下面的方式:

<div>
  <Route path="/" exact component={HomePage} />
  ... ...
</div>
複製代碼

(3) strict:嚴格匹配

若是path的最後帶有/,那麼url必須也帶有/才能匹配。舉例:

<Route path='/login/' strict />:能夠匹配/login/,不能匹配/login

(4) sensitive:大小寫敏感

3.1.2 渲染方法

這些屬性指明在匹配上路由後如何渲染。

(1) component:渲染組件

這是最多見的方式,路由匹配時渲染一個指定組件

<Route path='/users' component={UsersPage} />

(2) render:內聯渲染

component方式會經過React.createElement建立新元素,而後mount到DOM上,若是須要頻繁更新的話這種方式效率會比較低,這時候你能夠選擇內聯渲染方式。

<Route path='/users' render={props => (
  <div>
    <Component {...props}/>
  </div>
)}/>
複製代碼

(3) children:根據path匹配結果渲染子元素

前面兩種渲染方法都是隻有path匹配時才渲染,children渲染方式則比較特殊,它是針對子元素的,而且只返回一個match結果,你能夠根據match結果自行決定如何渲染子元素。舉個例子,在一個列表中,咱們但願高亮那些被匹配上的元素:

<ul>
  <ListItemLink to="/somewhere" />
  <ListItemLink to="/somewhere-else" />
</ul>;

const ListItemLink = ({ to, ...rest }) => (
  <Route
    path={to}
    children={({ match }) => (
      <li className={match ? "active" : ""}>
        <Link to={to} {...rest} />
      </li>
    )}
  />
);
複製代碼
3.1.3 路由屬性

這些屬性能夠在待渲染組件中經過props訪問到。

(1) match

match屬性中包含了路由匹配相關的參數:

  • params:參數鍵值對(好比前面的username)
  • isExact:是否精確匹配(是否指定了exact)
  • path:正則表達式(如/login/:username)
  • url:和path匹配上的部分(入/login/alice)

(2) location

location中包含了當前url相關的參數:

  • pathname:當前url
  • search:url中的查詢字符串(如?username=a&sort=b)
  • state:攜帶的特定狀態參數,是一個對象(如{ XXX: 'xxx' })

(3) history

history就是瀏覽器提供的history API,提供了一些路由函數:

  • push(path, [state]):頁面跳轉
  • replace(path, [state]):重定向
  • go(n):直接跳轉到第n個頁面
  • goBack():等價於go(-1)
  • goForward():等價於go(1)

3.2 <Switch>

若是咱們但願設置一系列的路由匹配規則,只渲染第一個匹配上的組件,該如何實現呢?這時候你就須要用到<Switch>組件。<Switch>中包含一組<Route>或者<Redirect>,只渲染第一個匹配的路由

import { Switch, Route } from 'react-router'

<Switch>
  <Route exact path="/" component={Home}/>
  <Route path="/about" component={About}/>
  <Route path="/:user" component={User}/>
  <Route component={NoMatch}/>
</Switch>
複製代碼

4.導航

react-router提供了一系列的導航組件,基本上就是<a>標籤的一個封裝。主要包括3種:

  • <Link>:最終渲染爲<a>
  • <NavLink>:path匹配時顯示爲高亮樣式
  • <Redirect>:重定向

舉例:

import { Link, NavLink } from 'react-router-dom'

<Link to="/about">About</Link>
<NavLink to="/faq" activeClassName="selected">
  FAQs
</NavLink>
複製代碼

另外,react-router還提供了其餘一些工具庫,好比支持組件的動態import(下載)的react-loadable,支持CSS轉場動畫的react-transition-group,有興趣的朋友能夠自行研究一下。

最後以一張思惟導圖結束本篇文章:

相關文章
相關標籤/搜索