做爲 React
全家桶的一員,若是咱們想要開發一個 React
應用,那麼 react-router
基本上是咱們繞不過去的基礎。基於此,對它的瞭解和使用也是必不可少的一步html
本文將重點介紹實際應用中經常使用的一些 API
以及實踐過程當中遇到的一些問題,目標很簡單:會用前端
基於react-router
v5.0.1
,WEB
應用程序
國際慣例,首先咱們須要安裝vue
npm install --save react-router-dom
從這一步開始,已經有同窗有疑問了:咱們明明在說 react-router
怎麼要下載安裝 react-router-dom
呢react
React Router
如今已經被劃分紅了三個包:react-router
,react-router-dom
,react-router-native
git
react-router
爲React Router
應用提供了核心的路由組件和函數,另外兩個包提供了特定環境的組件(瀏覽器和react-native
對應的平臺),不過他們也是將react-router
導出的模塊再次導出
由於咱們須要開發一個 web
應用,因此直接安裝 react-router-dom
就能夠了github
首先,讓咱們經過一個小小的示例來感知一下 react-router
web
import React from 'react' import ReactDom from 'react-dom' import { BrowserRouter, Route, Link, Switch } from 'react-router-dom' const Index = () => <div>Index頁面</div> const About = () => <div>About頁面</div> const App = () => { return ( <BrowserRouter> <div> <div> <ul> <li><Link to='/'>Index</Link></li> <li><Link to='/about'>About</Link></li> </ul> </div> <div> <Switch> <Route path='/' exact component={Index}></Route> <Route path='/about' exact component={About}></Route> </Switch> </div> </div> </BrowserRouter> ) } ReactDom.render(<App />, document.getElementById('app'))
經過上面的代碼咱們已經實現了路由的基本功能,匹配不一樣的路徑,渲染不一樣的組件。下面,咱們就上面的示例,認識一些 react-router
中高頻率出現的概念vue-router
React Router
應用程序的核心,每一個 router
都會建立一個 history
對象,用來保持對當前位置的追蹤npm
在 web
項目中,react-router-dom
提供了 BrowserRouter
和 HashRouter
路由。這兩個路由都會爲你建立一個專門的 history
對象。至於使用場景,通常狀況下若是咱們使用的是一個非靜態的站點、要處理不一樣的 url
就使用 BrowserRouter
,相反若是隻處理靜態的 url
,則使用 HashRouter
編程
Route
組件的主要職責:當連接符合匹配規則時,渲染組件
路由匹配是經過比較 Route
的 path
屬性和當前地址的 pathname
來實現的。當一個 Route
匹配成功時,它將渲染其內容,當它不匹配時就會渲染 null
。沒有路徑的 Route
將始終被匹配
Route
組件經常使用屬性:
path
: 字符串類型,用來匹配 ulr
exact
: boolean
類型,若是爲 true
,則只有在路徑徹底匹配 location.pathname
時才匹配component
: 只有當位置匹配時纔會渲染的 React
組件注意點:
Route
組件屬性都不是必須的,若是缺乏path
屬性,那麼將會匹配到任意url
<Route path='/' exact component={Index} /> <Route component={About} />
使用render
或者children
屬性能夠替代component
屬性,因爲render
與children
都是函數的形式,因此能夠在它們當中作一些比較複雜的邏輯
render
函數也是在匹配url
的時候渲染,而children
函數 任什麼時候候 都渲染,當路由匹配的時候match
是一個對象,不然爲null
當三者一塊兒使用的時候,優先級爲
children
>component
>render
<!-- 使用 render 屬性 --> <Route path='/about' render={() => <div>這個是render渲染的about頁面</div>} /> <Route path='/about' render={(props) => <About {...props} />} /> <!-- 使用 children 屬性 --> <Route path='/about' children={() => <div>這是一個children渲染的about頁面</div>} <Route path='/about' children={({match}) => match ? <div>1</div> : <div>2</div> }
渲染與該地址匹配的第一個子節點Route
或者Redirect
這個組件最重要的做用是能夠將 Route
組件分組
<Switch> <Route path='/user' render={()=><div>user頁面</div>} /> <Route path='/:id' render={()=><div>子成員</div>} /> <Route render={()=><div>about頁面</div>} /> </Switch>
在上面這個示例中,在沒有 Switch
組件包裹的狀況下,若是 ulr
是 /user
,那麼三個頁面將會所有匹配到。這樣的設計在必定程度上給咱們提供了便利,好比說一個公共頁面須要渲染好幾個組件的狀況。可是有時候咱們並不想訪問到所有的匹配組件,這個時候就能夠將這些 Route
組件使用 Switch
包裹起來,它將永遠渲染符合匹配項的第一個組件
注意點:
Switch
匹配的規則是同一個組中渲染第一個匹配組件,也就是說若是是包裹在兩個不一樣的 Switch
組件中的,會分別渲染匹配到的第一個組件Switch
組件中不能嵌套內置標籤元素,好比 div
span
,可是能夠嵌套組件,甚至能夠添加 path
屬性進行匹配, 實際上 Route
自己就是組件,可是建議仍是隻嵌套 Route
或者 Redirect
組件相信小夥伴們看過前面的示例以後,應該對 Link
不會陌生了。它的做用就是提供聲明式的可訪問導航
Link
經常使用屬性:
to
:能夠是 String
類型或者具備 pathname
、search
、hash
、state
任何屬性的對象pathname
: 表示要連接到的路徑的字符串
search
: 表示查詢參數的字符串形式
hash
: 放入網址的 hash
state
: 狀態持續到 location
replace
:boolean
類型,若是爲 true
,點擊連接將替換當前歷史記錄NavLink
一個特殊版本的Link
,當它與當前URL
匹配時,爲其渲染元素添加樣式屬性,其用法與Link
基本相同
注意點:
activeClassName
或者 activeStyle
屬性進行添加,簡單來講就是使用 class
類或者行內樣式NavLink
有一個 exact
屬性,若是爲 true
,則僅在位置徹底匹配時才應用 active
的類/樣式顧名思義,重定向組件,組件中的 to
屬性是必須的
屬性:
to
:string
類型或者一個對象(pathname
屬性是重定向到的 URL
)push
:boolean
類型,當 true
時,重定向會將新地址推入 history
中,而不是替換當前地址,就是經過 history.push
或者 history.replace
實現from
:重定向 from
的路徑名,簡單說就是將要進入的 url
exact
:徹底匹配 from
;至關於 Route.exact
這個組件在一些場景中有很好的效果,好比咱們登陸場景,前面咱們介紹過的 Route
組件渲染屬性使用 render
或者 children
的時候,就徹底能夠根據判斷條件執行不一樣的路由跳轉
<!-- 官網示例代碼 --> <Route exact path='/' render={()=>( loggedIn ? ( <Redirect to="/dashboard"/> ) : ( <PublicHomePage/> ) )} /> <!--或者--> <Route path='/about' children={({match})=>( match ? ( <About /> ) : ( <User /> ) )} />
前面介紹 Switch
組件時,有過它的身影,實際上它能夠和 Switch
組件很好的配合,好比:
<Switch> <Redirect from='/user' to='/about' /> <Route path='/user' render={()=><div>User頁面</div>} /> </Switch>
須要注意的地方:
from
屬性只能用於在 Redirect
內部渲染 Switch
時匹配地址Redirect
組件中 from
匹配的 Route
要在前面定義<!--錯誤姿式,這樣是沒有效果的--> <Route path='/user' render={()=><div>User頁面</div>} /> <Redirect from='/user' to='/about' />
默認狀況下,通過路由匹配的組件才擁有路由參數,咱們就能夠在其中使用 編程式導航,好比:
this.props.history.push('/about')
然而,不是全部的組件都是與路由相連的,好比直接在瀏覽器輸入地址打開的。這個時候咱們訪問組件 props
的時候,它是一個空對象,就沒辦法訪問 props
中的 history
、match
、location
等對象
因此 這個時候 withRouter
閃亮登場
withRouter
的用法很簡單:
import React, { Component } from 'react'; <!--引入--> import { Route, Link, Switch, withRouter } from 'react-router-dom' class App extends Component { render() { <!-- 沒有使用 withRouter 的時候,是一個空對象--> console.log(this.props) return ( <div> <Link to='/'>Index</Link> <Link to='/about'>About</Link> <Switch> <Route path='/' exact render={()=> <div>Index頁面</div>} /> <Route path='/about' render={()=> <div>About頁面</div>} /> </Switch> </div> ); } } <!--執行--> export default withRouter(App)
固然,還有不少種使用方式,好比經過 withRouter
監聽 loaction
對象改變文檔標題或者配合 redux
使用等等
詳見 示例demo
瞭解了 react-router
的這些基本知識點,貌似咱們已經能夠寫出來一個用路由搭建的項目了。可是,請暫時停下腳步想一下:在一個項目當中,若是咱們遇到嵌套的路由呢、動態參數的路由呢?固然,只用前面瞭解到的東西,徹底能夠寫出來,但那是在是太 low
了
在解答前面的兩個問題以前,咱們須要先了解一個 match
對象
相信在前面的 withRouter
模塊,小夥伴們已經知道了 match
對象的存在,在動態路由和路由嵌套時,咱們會常常和它打交道
一個match
對象中包涵了有關如何匹配URL
的信息
它包含如下屬性:
params
:與動態路徑的 URL
對應解析,它裏面包含了動態路由裏面的信息path
:用於匹配的路徑模式url
:用於匹配部分的 URL
isExact
- 若是爲 true
匹配整個 URL
(沒有結尾字符)注意點:
Route
沒有 path
,那麼將會一直與他最近的父級匹配。這也一樣適用於 withRouter
match
對象中的 url
和 path
,簡單來講 path
是匹配的規則, url
則是實際匹配到的路徑瞭解了 match 對象,動態路由的定義其實很簡單
<Link to='/video/1'>視頻教程1</Link> <Link to='/video/2'>視頻教程2</Link> <Route path='/video/:id' component={Video} />
Route
組件能夠匹配到 Link
連接跳轉的路徑,而後再 match
對象的 params
屬性中就能夠拿到動態數據的具體信息
React Router 4
再也不提倡中心化路由,取之的是路由存在於佈局和 UI
之間,Route
自己就是一個組件
實現路由嵌套最簡單的方式:
<!--父組件--> <Route path='/workplace' component={Workplace} /> <!--子組件--> <Route path='/workplace/money' component={Money} />
固然,使用 match
來進行匹配會更加優雅
<!--父組件--> <Route path='/video' component={Video} /> <!--子組件--> <Route path={`${this.props.match.url}/react`} component={ReactVideo} />
注意點:
exact
使用這樣的方式來配置路由規則,咱們就只須要考慮 component
的渲染時機就能夠了。可是,一樣的也會給咱們帶來一些問題,好比說路由規則不是很直觀,尤爲是對於寫過 vue
的小夥伴來講,要是有一個像配置 vue-router
規則的東西就行了。這個時候,咱們能夠試着去了解一個這個東西了 react-router-config
詳見 示例demo
突如其來的結束語
關於 react-router
的基本用法就是想上面介紹的那樣,可是想要探究更多有意思或者更優雅的用法,還須要咱們在具體的項目中去磨練,好比說路由的拆分、按需加載等等一系列東西
若是你也對 React
中的其餘內容感興趣,想要了解更多前端片斷,能夠 點擊這裏 ,歡迎 star
關注