react路由解決方案


react-router:是react router的核心庫

react-router-dom:是網頁路由的解決方案,依賴於react-router

react-router-native:是react-native解決移動端路由的解決方案,依賴於react-router

下面講述的是react-router-dom的使用

這里用的react-router版本是5.x

react-router5.x版本和react-router3.x使用上有很大不同

1安裝路由模塊

npm i –S react-router-dom

2路由的定義

App.jsx

image

這里定義了4個頁面

<Router>定義一個路由實例,相當於一個路由容器

<Switch>標簽讓路由只能匹配單個<Route>,不具包含性的匹配多個路由

5.x的路由具有包含性和3.x的路由完全不同

exact屬性讓route進行嚴格匹配,只有路徑完全一致才會匹配成功,默認值true,可以省略不寫

eq:

image

      在網頁中匹配根路徑’/’,路由匹配會按從上到下的順序進行匹配,如果沒有<Swith>標簽,就會成功匹配’/’,’/about’,’/inbox’,’/coder’所有的<Route>標簽,從而展示其相關的組件。

添加<Swith>標簽后,路由只能匹配單個<Route>標簽,因此這里只會匹配到path=’/’的<Route>標簽

但如果在網頁中匹配’/about’,這時還是會匹配到path=’/’的路由,因此需要給path=’/’的<Route>標簽添加exact屬性讓其進行嚴格匹配,只有路徑完全等於’/’時才會成功匹配,添加exact屬性后路由就不會匹配到path=’/‘的路由上,而是匹配到path=’about’的路由

3.將路由渲染到頁面

index.js

image

下面敘述相關的詳細的組件

目錄結構:

image

Dashboard.jsx  網頁根組件

image

這里有個公共組件Header

Header.jsx

image

<Link>標簽用來進行路由跳轉,默認會被渲染成a標簽

About.jsx

image

Inbox.jsx

image

這里面嵌套了兩個子路由,對應的組件分別是MessageLinkComponent和Message

其中一個是動態路由,以id值作為動態路徑

獲取父級路由的路徑path:this.props.match.path,這里獲取到的path是 ‘/inbox’

與this.props.match.url比較:

this.props.match.path獲取的是純路徑,即定義好的路徑  ‘/index/:id’

this.props.match.url獲取的是資源的路徑地址  ‘/index/123’

子路由組件:MessageLinkComponent.jsx

image

實現子路由的跳轉,並把id值當成動態路徑傳出

子路由組件:Message.jsx

image

子路由跳轉的內容顯示

id值的獲取:this.props.match.params.id

Coder.jsx

image

定義了一個子路由,其對應的組件是CoderContent

並且定義了子路由跳轉的Link,實現子路由跳轉,將相關數據以鍵值對存放於路徑中並傳遞出去

CoderContent.jsx

image

通過get傳值傳遞來的鍵值對用node的url模塊進行解析,解析出一個以json對象保存的query對象,並將其展示在頁面上

url.parse(this.props.location.search,true).query

路由模塊的抽離

將路由的定義抽離成一個配置文件routesConfig.js

routesConfig.js

image

相關頁面也需要改寫

App.jsx

image

這里用三元表達式代替了if-else語句的嵌套

注意:子路由的嵌套要將component屬性改寫成一個render函數,這樣才能將children子路由對象傳遞給props參數

image

render函數是一個帶props參數的箭頭函數,結果返回一個react組件實例對象(jsx對象)

並把children子路由掛載在實例對象的children屬性上,相當於覆蓋了props.children屬性。

 

從這里可以看出<Route>標簽的作用僅僅只是充當了一個中間組件,最后還是需要通過render

函數來渲染相關的即將展示的組件,並通過props參數把掛在<Route>標簽上的屬性傳給組件實例

例如:<Route>上的path屬性最終會以this.props.match.path的形式在react組件實例中獲取到

 

Inbox.jsx

image

Coder.jsx

image

image

js實現路由跳轉

網上有很多種方法實現,這里使用比較簡單的兩種方法

1.官方推薦的組件內路由跳轉

官方推薦使用高級路由組件withRouter來包裹需要用到跳轉的組件。

這里對組件Header.jsx進行修改

image

被withRouter包裹的Header會給props注冊一個history對象,這個history對象正是整個路由默認使用的history對象(創建BrowserRouter組件后會有一個默認的history,但不會直接暴露出來給你使用)

history對象內容:

image

可以通過event.target獲取dom對象,進而通過js操作dom獲取元素屬性to的值,即獲取跳轉路徑,並通過this.props.push()來進行跳轉

eq: this.props.history.push(e.target.getAttribute('to'))

也可以通過event.target.dataset.to來獲取路徑值,不過進行跳轉的標簽上要有定義data-to屬性來保存路徑

eq: this.props.history.push(e.target.dataset.to)

2.自己創建一個history對象實例來控制跳轉 (比較自由)

創建history模塊

image

history.js

image

這里用了react的history庫來創建,並將實例導出。

注意將history對象引入到Router組件中,讓整個路由實例使用我們創建出來的history對象,否則無法生效

App.jsx

image

image

導入后發出警告:

image

原來BrowserRouter忽略了history屬性,因此通過BrowserRouter創建的路由也都不用手動導入history。

為了能使用自定義的history,只好不使用提供好的BrowserRouter組件來創建路由,而是用最原始的Router組件來創建路由實例。

image===》

image

然后只需要在想要使用跳轉的組件中導入我們創建好的history實例,並操作history對象就能實現跳轉了

eq:

import history from ‘modules/history’

history.push(e.target.getAttribute('to'))

以Header.jsx為例:

image

實際上這里的this.props.history和導入的history已經是同一個對象了

實驗:

console.log(history==this.props.history) //true

推導可以知道withRouter組件給Header注冊的this.props.history屬性,來自於App.jsx中導入的history => <Router history={history}> ,並且通過withRouter傳遞給其他組件

補充

由於Route組件進行的條件判斷太過繁雜,於是將Switch組件和Route組件組合封裝成一個Routes組件,避免頁面數量多時,總要重復寫這段判斷代碼

Routes.js

image

由於對Route組件外部包裹了Routes這樣一個組件,導致某些組件在調用Routes時,沒有把上一層的Route組件的屬性傳遞下去,Route組件其實就是個中間組件並且包裹了個普通組件,並把Route上的屬性傳遞給普通組件。

正常:Route.props –> Component.props

嵌套后: Route.props –> Component.props –>Route2.props –> Component2.props

Component.props –>Route2.props 這個階段會用到 Component.props的部分值

包裹Routes后:Routes.props –> Route.props  –> Component.props 

因此進行路由嵌套后是這個樣:

Routes.props –> Route.props  –> Component.props  -> Routes2.props –> Route2.props  –> Component2.props

這里得解決:Component.props  -> Routes2.props 這個階段的傳值,Routes2作用其實就是承接Component中的props,目的是為了能讓Route2能正常工作

於是得進行手動傳值:<Routes {...this.props}></Routes>

並且在Routes組件中增加了判斷,判斷接下來進行渲染的config用的是routesConfig還是由組件傳遞下來的children

this.props.children?(this.config=this.props.children):(this.config=routesConfig)

修改后的App.jsx變得極為簡單:

image

Inbox.jsx也一樣

image

同理作用於Coder.jsx


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM