在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的相關組件。正則表達式
react-router內部其實是利用了瀏覽器的history API,所以在v3版本中咱們須要在頂層的<Router>組件中傳入一個history屬性。在v4版本中爲咱們封裝了一個<BrowserRouter>組件,咱們須要把它包在全部組件的最外層:瀏覽器
import { BrowserRouter } from 'react-router-dom'
const App = () => (
<BrowserRouter>
... ...
</BrowserRouter>
)
複製代碼
另外還有一個<HashRouter>組件,是爲了兼容之前版本的瀏覽器,已經不推薦使用了。bash
路由匹配主要涉及兩個組件:<Route>和<Switch>,下面分別介紹。react-router
<Route>組件包含3類屬性:匹配屬性、渲染方法、路由屬性。app
這些屬性是爲了設定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:大小寫敏感
這些屬性指明在匹配上路由後如何渲染。
(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>
)}
/>
);
複製代碼
這些屬性能夠在待渲染組件中經過props訪問到。
(1) match
match屬性中包含了路由匹配相關的參數:
(2) location
location中包含了當前url相關的參數:
(3) history
history就是瀏覽器提供的history API,提供了一些路由函數:
若是咱們但願設置一系列的路由匹配規則,只渲染第一個匹配上的組件,該如何實現呢?這時候你就須要用到<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>
複製代碼
react-router提供了一系列的導航組件,基本上就是<a>標籤的一個封裝。主要包括3種:
舉例:
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,有興趣的朋友能夠自行研究一下。
最後以一張思惟導圖結束本篇文章: