概要
開發單頁應用, 首先繞不開的內容就是路由, react router v4 版本是最新的版本. 和以前的版本相比, 成熟了不少, 也簡單了不少, 使用起來更加方便.javascript
核心 component
react-router V4 能夠用於 Web 和 Native. 這裏主要討論基於 Web 的應用.css
react-router 有不少 Components, 可是隻要掌握下面 3 個 Component 就能夠管理好 react 應用的路由了.html
Router component
Router 是整個應用的路由. 在 Web 應用中, 使用 BrowerRouter 來包裝 Appjava
<BrowserRouter> <App /> </BrowserRouter>
而後, 在 App component 中, 就可使用 Route 來定義各個路由對應的 componentreact
Route component
每一個 Route 都是一個具體的路由, 對應一個具體的頁面. Route 能夠對應一個 Component, 也能夠直接寫個匿名的 render 函數.redux
Route 中最經常使用的屬性就是 path, 也就是路由的地址, 除此以外, Route 最重要的做用是會將 { match, location, history } 3 個屬性注入到對應的 Component 或者 render 函數中.bash
Link component
Link 是用來導航的, 也就是在不一樣 Route 之間切換就會用到 Link.react-router
經常使用路由示例
示例工程
示例工程的建立採用 create-react-app 工具.app
$ create-react-app route-test $ cd route-test $ yarn add react-router-dom
基本使用
修改工程中的 App.js 文件, 增長 route 的 sampledom
import React, { Component } from 'react' import { BrowserRouter as Router, Route, Link } from 'react-router-dom' import './App.css' const Index = () => <h2>Home</h2> const About = () => <h2>About</h2> const Users = () => <h2>Users</h2> class App extends Component { render() { return ( <Router> <div> <nav> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/about/">About</Link> </li> <li> <Link to="/users/">Users</Link> </li> </ul> </nav> <Route path="/" exact component={Index} /> <Route path="/about/" component={About} /> <Route path="/users/" component={Users} /> </div> </Router> ) } } export default App
這個示例中, 就包含了 3 個經常使用組件 Router, Route 和 Link
路由參數
路由的參數能夠加在 path 上, 下面的示例中, Users Component 能夠經過注入的 match 來獲得 URL 中的參數.
import React, { Component } from 'react' import { BrowserRouter as Router, Route, Link } from 'react-router-dom' import './App.css' const Index = () => <h2>Home</h2> const About = () => <h2>About</h2> const Users = ({ match }) => ( <h2> User is {match.params.name}, age: {match.params.age} </h2> ) class App extends Component { render() { return ( <Router> <div> <nav> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/about/">About</Link> </li> <li> <Link to="/users/test/16">Users</Link> </li> </ul> </nav> <Route path="/" exact component={Index} /> <Route path="/about/" component={About} /> <Route path="/users/:name/:age" component={Users} /> </div> </Router> ) } } export default App
query 參數
除了上面那種 RESTful 的參數方式, 也能夠經過 query 來傳遞參數. 下例中, 經過 location.search 來獲取 querystring, 至於解析 querystring, 已有不少現成的方法可使用.
import React, { Component } from 'react' import { BrowserRouter as Router, Route, Link } from 'react-router-dom' import './App.css' const Index = () => <h2>Home</h2> const About = ({ match, location }) => ( <h2>About's search string: {location.search}</h2> ) const Users = ({ match }) => ( <h2> User is {match.params.name}, age: {match.params.age} </h2> ) class App extends Component { render() { return ( <Router> <div> <nav> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to={{ pathname: '/about/', search: '?name=test&age=16' }}> About </Link> </li> <li> <Link to="/users/test/16">Users</Link> </li> </ul> </nav> <Route path="/" exact component={Index} /> <Route path="/about/" component={About} /> <Route path="/users/:name/:age" component={Users} /> </div> </Router> ) } } export default App
FAQ
在剛開始使用 react-router 時, 可能會有些疑問, 我整理了本身在使用中一些疑惑:
match 是如何注入到 Component 中的
match, location, history 這 3 個 object, 是由 Route Component 做爲 props 注入到它的 render 方法, 或者 component={xxx} prop 對應的組件中的
match.path 和 match.url 有什麼區別
- match.path 是用來作匹配用的, 也就是在 Route 中使用的
- match.url 是用來遷移頁面用的, 也就是在 Link 中使用的
好比上面的例子中, 對於 /users
- match.path 是 users:name/:age
- match.url 是 /users/test/16
BrowserRouter 和 HashRouter 有什麼區別
- BrowserRouter 是用於和 Server 有交互的 Router
- HashRouter 是用於靜態文件服務的 Router
Route 和 Switch 的區別
當有多個 Route 並列時, 若是外層沒有包裹 Switch, 那麼匹配到的 Route 都會被 render, 若是有 Switch, 那麼只會 render 第一個匹配上的 Route
Route 若是不設置 path, 則每次都會匹配成功
Link 和 NavLink 的區別
NavLink 是一種特殊的 Link, 它能夠設置一些 active 時的樣式.
路由信息和 redux 狀態管理如何結合
路由信息本質上也是一種狀態信息, 放不放在 redux 中來管理, 相信不少人都會糾結. 官方的建議是不要把路由的狀態放在 redux 的 store 中來管理, 理由以下:
- 路由狀態通常只有 Components 才關心, 無論放不放在 redux 中, Component 的代碼不會有什麼改變
- 大部分狀況下, 路由跳轉都是經過 Link, NavLink, Redirct 來完成, 若是須要經過代碼, 或者異步 action 中來跳轉, 能夠經過傳入 history 對象來完成.
- 路由變化通常不須要經過時間旅行(time travel, redux 的一個調試工具)來 debug.