對於以前沒有接觸過 React Router 的同窗來講,必定要注意:最新的React Router版本是 V5 。除此以外,還有 V2 V3 V4 版本。其中V4和V5版本的用法和理念基本上是一致的,可是和以前的V二、V3版本有較大差別。css
因此在學習以前必定要弄清楚本身使用的是哪個版本,若是是V4或者V5,V4和V5兩個版本的文檔筆記均可以參考;若是你用的是V2或者V3,那麼必定要找到對應的文檔筆記。react
在我學習React Router的時候,使用的是V5,因此這篇筆記也是對 React Router V5 的一些總結。若是你是一名React小白,我想經過這篇筆記,你能夠基本會使用React Router。若是你想更深層次地理解React Router,能夠訪問:reacttraining.com/react-route… 。webpack
在V4和V5版本中,React Router分紅了兩個大的方向:React Web Router 和 React Native Router 。若是你是建立的React Web應用,就使用React Web Router ,這裏咱們使用的就是這個Router,因此執行如下命令進行安裝:web
npm install --save react-router-dom
複製代碼
想要在React項目中使用路由,必不可少的有兩個組件(component): BrowserRouter 和 Route 。在React項目中,經過如下命令引入這兩個組件:shell
import { BrowserRouter, Route } from "react-router-dom";
複製代碼
BrowserRouter 組件是React Router的核心,Route組件是React Router的具體配置。舉個例子來講:BrowserRouter 組件就像是一個文具盒,Route組件就像是一件件文具同樣,須要放在這個盒子裏。這樣咱們在使用文具的時候,只須要打開文具盒,從裏面取出便可。npm
瞭解了這層關係,咱們就能夠在React中配置路由了,配置很是簡單,示例代碼以下:瀏覽器
// React 應用中的 App.js 文件
import React from 'react';
import { BrowserRouter, Route } from 'react-router-dom'
import Set from './views/set/Set'
import Help from './views/help/Help'
class App extends React.Component {
render() {
return (
<BrowserRouter>
<Route path="/help" component={Help} />
<Route path="/set" component={Set} />
</BrowserRouter>
);
}
}
export default App;
複製代碼
在App.js文件中配置完車以後,而後在React入口文件中(通常是index.js文件),引入App.js文件並掛載到頁面上,示例代碼以下:服務器
// React 應用中的入口文件 index.js
import React from 'react'
import { render } from 'react-dom'
import App from './App'
render((
<App /> ), document.getElementById('root')) 複製代碼
掛載完成以後,經過npm run start
等命令啓動本地開發服務器,就能夠經過路由訪問咱們的React項目了。實例以下:react-router
簡單介紹一下以上代碼中的路由配置規則,以這條路由配置爲例:dom
<Route path="/help" component={Help} />
複製代碼
Help 是咱們以前定義好的一個React組件,該組件的定義代碼以下:
import React, { Component } from 'react'
class Help extends Component {
render() {
return (
<div className="help-box"> 幫助與反饋 - 頁面 </div>
);
}
}
export default Help;
複製代碼
當咱們在瀏覽器地址欄中輸入 http://localhost:3000/help
的時候,React Router 會匹配到 <Route path="/help" component={Help} />
這一條記錄,而後就會在當前位置渲染對應的component。
注意是當前位置,說得更通俗一點:就是使用將Help組件中的代碼替換掉 <Route path="/help" component={Help} />
代碼,進而渲染出路由對應的component。關於這一點,後面會有更詳細的解釋。
經過上面的配置,咱們已經能夠經過輸入URL來跳轉路由,可是更多狀況下,咱們但願能夠經過點擊頁面上的連接進行路由的跳轉,好比如下的示例:
想要實現這一點,咱們只須要引入 Link 這個組件便可,具體代碼以下:
// React 應用中的 App.js 文件
import React from 'react';
import { BrowserRouter, Route, Link } from 'react-router-dom' // 引入 Link 組件
import Set from './views/set/Set'
import Help from './views/help/Help'
class App extends React.Component {
render() {
return (
<BrowserRouter>
{/* 注意 Link 組件必定要位於 BrowserRouter 組件中 */}
<ul>
<li><Link to="/help">Help</Link></li>
<li><Link to="/set">Set</Link></li>
</ul>
<Route path="/help" component={Help} />
<Route path="/set" component={Set} />
</BrowserRouter>
);
}
}
export default App;
複製代碼
如今咱們已經掌握了React Router的基本使用,可是這個時候咱們掌握的知識還不足以讓咱們熟練地使用它,因此下面爲你們介紹React Router更多內容。
在對Route進行配置的時候,咱們能夠傳如下參數:path、exact、component、render、children 。這些參數都不是必須的,也就是說,咱們有不少中配置Route的方式,常見的有如下幾種:
<BrowserRouter>
<Route component={Wallet} />
<Route path="/" component={Index} />
<Route exact path="/" component={Index} />
<Route path="/help" component={Help} />
<Route path="/render" render={ () => { return <h1>我是匹配到的路由</h1> } } />
</BrowserRouter>
複製代碼
這裏分別介紹以上五種Route的配置方式:
<Route component={Wallet} />
在配置Route的時候沒有指定 path 屬性,這時只要你打開項目,不管你訪問什麼路徑,這個Route都會匹配到。
<Route path="/" component={Index} />
配置Route的時候,指定 path="/"
,和上面配置的效果同樣,只要你打開項目,不管你訪問什麼路徑,這個Route都會匹配到。這種配置方式咱們成爲 "非嚴格匹配" ,你在項目中訪問的任何一個路徑,裏面都會包含path="/"
的路徑。因此不管訪問什麼路徑,這個Route都會匹配到。
<Route exact path="/" component={Index} />
和上面一條的配置方式不一樣,這裏在配置Route的時候,傳入了 exact 屬性,說明這個配置方式是 "嚴格匹配" ,只有當咱們訪問項目的根路徑的時候,纔會匹配到這個Route。好比:localhost:3000/ 。
<Route path="/help" component={Help} />
一條很常規的Route配置方式,當咱們訪問"/help"路徑的時候,匹配到這個Route,進而渲染出對應的component。
<Route path="/render" render={ () => { return <h1>我是匹配到的路由</h1> } } />
和上一條路由配置不一樣的是,這裏沒有component屬性,而是換成了render屬性。該屬性是一個函數,當匹配到這個Route的時候,頁面將會渲染出這個函數返回的內容。
Switch組件的使用其實很是簡單,舉個例子:若是說BrowserRouter組件是一個大的文具盒的話,那麼Switch組件就是這個大文具盒中的一個小袋子,Route組件就是這個小袋子中的一支鉛筆,咱們須要鉛筆的時候,直接從這個小袋子裏面取出一支便可。注意:是最多隻能取出一支鉛筆。
也就是說,當進行路由匹配的時候,一旦匹配到了Switch組件中的一個Route,那麼就不會再繼續匹配。好比如下實例:
<BrowserRouter>
<Switch>
<Route component={Wallet} />
<Route path="/" component={Index} />
<Route path="/help" component={Help} />
<Route path="/render" render={() => { return <h1>我是匹配到的路由</h1> }} />
</Switch>
</BrowserRouter>
複製代碼
若是咱們訪問 "localhost:3000/help" 路徑,雖然前三個Route都匹配,可是頁面只會渲染第一個匹配到的Route,其餘的都被忽略。看到這裏你可能會問,這個組件有什麼做用呢?能夠在如下場景中發揮做用:若是當前路徑沒有匹配到任何Route的時候,路由跳轉到 404 頁面,那麼就能夠這樣寫:
<BrowserRouter>
<Switch>
<Route path="/set" component={Set} />
<Route path="/help" component={Help} />
<Route path="/render" render={() => { return <h1>我是匹配到的路由</h1> }} />
<Route component={NotFound} />
</Switch>
</BrowserRouter>
複製代碼
經過上面的配置,若是當前路徑有匹配到最後一個以外的Route,那麼就顯示對應內容,再也不繼續匹配;若是沒有匹配到最後一個以外的Route,就顯示最後一個Route,由於這個Route能夠匹配任何路徑。能夠把這個Route對應到 404 頁面。
前面講述了Route的配置和匹配規則,下面咱們講述一下,當路徑匹配到Route以後,會如何渲染對應的內容。
以前有提到過:是在 當前位置 渲染內容,對於一些剛入門的小白來講,可能不能馬上理解當前位置是什麼位置。因此咱們舉個例子,好比咱們在項目的App.js組件中有如下配置代碼:
class App extends React.Component {
render() {
return (
<div className="content">
<BrowserRouter>
<Route exact path="/" component={Index} /> {/* 位置 A */}
<Route path="/help" component={Help} /> {/* 位置 B */}
<Route path="/set" component={Set} /> {/* 位置 C */}
</BrowserRouter>
</div>
);
}
}
複製代碼
那麼當路徑爲 "help" 的時候,就會匹配到第二個Route,那麼React Router就會在 位置B 對應的這一行將 Route 組件替換成Help組件;而其餘沒有匹配到的Route,會被替換成null,至關於將這些 Route 組件直接刪去。最終的結果如如下代碼所示:
// Help 組件的定義代碼能夠在上文中找到
class App extends React.Component {
render() {
return (
<div className="content"> <div className="help-box"> 幫助與反饋 - 頁面 </div> </div>
);
}
}
複製代碼
之因此講這麼一個知識點,是爲後面介紹如何配置嵌套路由作準備,這裏能夠先提一下:若是咱們想在 組件A中 嵌套幾個子路由,那麼就能夠將這幾個Route配置,寫到組件A中,一旦路徑匹配到了這些Route,就會在組件A中對應的位置渲染子路由對應的組件。聽不懂不要緊,後面會有詳細的解釋。
經過上面的筆記,你可能會認爲:Route組件必須位於BrowserRouter組件中,且兩個組件必須在同一個文件中。
其實否則,從代碼結構上說,Route組件確實必須位於BrowserRouter組件中,可是兩個組件不必定非要在一個文件中,只要打包編譯以後,兩個組件知足Route組件位於BrowserRouter組件中就能夠。好比如下的寫法也是徹底正確的:
// 項目的入口文件 index.js
import React from 'react'
import { render } from 'react-dom'
import App from './App'
import { BrowserRouter } from 'react-router-dom'
render((
<BrowserRouter> <App /> </BrowserRouter>
), document.getElementById('root'))
複製代碼
// App.js 文件
import React from 'react';
import { Route, NavLink } from 'react-router-dom'
import Set from './views/set/Set'
import Help from './views/help/Help'
import Index from './views/index/Index'
import Wallet from './views/wallet/Wallet'
class App extends React.Component {
render() {
return (
{/* 注意這裏已經沒有了 BrowserRouter 組件 */}
<div className="content">
<ul>
<NavLink activeClassName="selected" to="help">help</NavLink >
<NavLink activeClassName="selected" to="index">index</NavLink >
<NavLink activeClassName="selected" to="wallet">wallet</NavLink >
<NavLink activeClassName="selected" to="set">set</NavLink >
</ul>
<Route path="/help" component={Help} />
<Route path="/index" component={Index} />
<Route path="/wallet" component={Wallet} />
<Route path="/set" component={Set} />
</div>
);
}
}
export default App;
複製代碼
嵌套路由,顧名思義就是在一個主路由匹配到的頁面中再配置一些路由,咱們如今就來說述如下如何使用 React Router 配置嵌套路由,配置完成以後,咱們會看到如下效果:
在以前的基礎之上,咱們已經配置好了一級路由,便可以通關點擊 set 按鈕跳轉到匹配到的Route對應的組件中,即Set組件,具體配置能夠參考上一個代碼塊中的代碼。
下面咱們要作的就是在Set組件中,進行配置二級路由,即嵌套路由。配置很是簡單,這裏先直接給出代碼:
import React, { Component } from 'react'
import { Route, Link } from 'react-router-dom'
import SetSystem from '../SetSystem'
import SetPerson from '../SetPerson'
import SetTime from '../SetTime'
import './Set.scss'
class Set extends Component {
componentDidMount() {
// 當前頁面匹配到的路徑,這裏是"/set"
// 使用這個路徑,配置Route和Link
console.log(this.props.match.path);
}
render() {
return (
<div className="set-box">
我的設置 - 頁面
<div className="link-list">
<Link to={`${this.props.match.path}/system`}>system</Link>
<Link to={`${this.props.match.path}/person`}>person</Link>
<Link to={`${this.props.match.path}/time`}>time</Link>
</div>
<div className="child-router">
<Route path={`${this.props.match.path}/system`} component={SetSystem} />
<Route path={`${this.props.match.path}/person`} component={SetPerson} />
<Route path={`${this.props.match.path}/time`} component={SetTime} />
</div>
</div>
);
}
}
export default Set;
複製代碼
注意代碼中咱們引入了 Set.scss 樣式文件,給頁面元素添加一些很是簡單的樣式,具體樣式你能夠自定義,這裏的示例代碼以下:
.set-box {
.link-list {
a {
margin: 0px 10px;
}
}
}
複製代碼
代碼書寫完成以後,咱們就配置好了嵌套路由,啓動項目你就能夠看到上面GIF中展現的效果。這裏對上面的配置作簡單的解釋:
首先再提一下:匹配到的Route會在 當前位置 渲染匹配到的內容(這個內容多是component組件,render函數返回的結果等)。
就是由於React Router的這個特性,咱們才能配置嵌套路由,不然,及時匹配到了Route,可是咱們不知道它的渲染位置,也不能實現此功能。
其次再說一下 this.props.match
這個屬性,經過這個屬性,咱們能夠得到當前頁面,即一級路由匹配到的組件對應的路徑,在這裏 this.props.match
的值是 "/set"。
瞭解了這一點,咱們就能夠在 this.props.match
的幫助下,設置二級路由的路徑。因此如下兩種寫法是等價的,可是第一種寫法更加靈活:
{/* 第一種寫法 */}
<Link to={`${this.props.match.path}/system`}>system</Link>
<Route path={`${this.props.match.path}/system`} component={SetSystem} />
{/* 第二種寫法 */}
<Link to="/set/system">system</Link>
<Route path="/set/system" component={SetSystem} />
複製代碼
最後再再說一下 Route組件 和 BrowserRouter組件 的位置問題。初次接觸React Router的小白可能會問:在設置嵌套路由的時候,Route組件怎麼沒有包含在BrowserRouter組件中?
事實上,在使用webpack將代碼打包打包編譯以後,Route組件已經包含在BrowserRouter組件中了。在代碼層面咱們能夠這樣理解:Route組件包含於Set組件中,Set組件包含於App組件中,App組件包含在BrowserRouter中。因此Route組件已經包含在BrowserRouter組件中。
囉囉嗦嗦寫完了對React Router的總結,內容挺多可是都很基礎,但願能夠幫到剛剛入門的小白。
若是大神們看到錯誤之處,還但願各位能及時指正。