![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iZiVzY1E2N3MDZmljY2kTOxgTZ0kDMhhTN3QDN5cTMj9CX5d2bs92Yl1iclB3bsVmdlR2LcNWaw9CXt92Yu4GZjlGbh5yYjV3Lc9CX6MHc0RHaiojIsJye.png)
大家好,我是小丞同學,一名大二的前端愛好者
這篇文章是學習 React 中 React 路由的學習筆記
非常感謝你的閱讀,不對的地方歡迎指正
願你忠于自己,熱愛生活
引言
在上一篇中,我們學習了 React 中使用路由技術,以及如何使用 MyNavLink 去優化使用路由時的代碼備援的情況。
這一節我們繼續上一篇 React 路由進行一些補充
1. Switch 解決相同路徑問題
首先我們看一段這樣的代碼
<Route path="/home" component={Home}></Route>
<Route path="/about" component={About}></Route>
<Route path="/about" component={About}></Route>
這是兩個路由元件,在2,3行中,我們同時使用了相同的路徑 /about
我們發現它出現了兩個 about 元件的内容,那這是為什麼呢?
其實是因為,Route 的機制,當比對上了第一個 /about 元件後,它還會繼續向下比對,是以會出現兩個 About 元件,這時我們可以采用 Switch 元件進行包裹
<Switch>
<Route path="/home" component={Home}></Route>
<Route path="/about" component={About}></Route>
<Route path="/about" component={About}></Route>
</Switch>
在使用 Switch 時,我們需要先從 react-router-dom 中暴露出 Switch 元件
這樣我們就能成功的解決掉這個問題了
2. 解決二級路由樣式丢失的問題
當我們将路徑改寫成 path="/ljc/about" 這樣的形式時,我們會發現當我們強制重新整理頁面的時候,頁面的 CSS 樣式消失了。這是因為,我們在引入樣式檔案時,采取的是相對路徑,當我們使用二級路由的時候,會使得請求的路徑發生改變,浏覽器會向 localhost:3000/ljc 下請求 css 樣式資源,這并不是我們想要的,因為我們的樣式存放于公共檔案下的 CSS 檔案夾中。
我們有幾種方法,可以解決這個問題
将樣式引入的路徑改成絕對路徑
引入樣式檔案時不帶 .
使用 HashRouter
我們一般采用第一種方式去解決
3. 路由的精準比對和模糊比對
路由的比對有兩種形式,一種是精準比對一種是模糊比對,React 中預設開啟的是模糊比對
模糊比對可以了解為,在比對路由時,隻要有比對到的就好了
精準比對就是,兩者必須相同
我們展示一個模糊比對的例子
<MyNavLink to = "/home/a/b" >Home</MyNavLink>
這個标簽比對的路由,我們可以拆分成 home a b,将會根據這個先後順序比對路由
<Route path="/home"component={Home}/>
就可以比對到上面的這個路由,因為它比對的是 home
當比對的路由改成下面這樣時,就會失敗。它會按照第一個來比對,如果第一個沒有比對上,那就會失敗,這裡的 a 和 home 沒有比對上,很顯然會失敗
<Route path="/a" component={Home}/>
當我們開啟了精準比對後,就我們的第一種比對就不會成功,因為精準比對需要的是完全一樣的值,開啟精準比對采用的是 exact 來實作
<Route exact={true} path="/home" component={Home}/>
4. 重定向路由
在我們寫好了這些之後,我們會發現,我們需要點選任意一個按鈕,才會去比對一個元件,這并不是我們想要的,我們想要頁面一加載上來,預設的就能比對到一個元件。
這個時候我們就需要時候 Redirecrt 進行預設比對了。
<Redirect to="/home" />
當我們加上這條語句時,頁面找不到指定路徑時,就會重定向到 /home 頁面下是以當我們請求3000端口時,就會重定向到 /home 這樣就能夠實作我們想要的效果了
5. 嵌套路由
嵌套路由也就是我們前面有提及的二級路由,但是嵌套路由包括了二級、三級…還有很多級路由,當我們需要在一個路由元件中添加兩個元件,一個是頭部,一個是内容區
我們将我們的嵌套内容寫在相應的元件裡面,這個是在 Home 元件的 return 内容
<div>
<h2>Home元件内容</h2>
<div>
<ul className="nav nav-tabs">
<li>
<MyNavLink className="list-group-item" to="/home/news">News</MyNavLink>
</li>
<li>
<MyNavLink className="list-group-item " to="/home/message">Message</MyNavLink>
</li>
</ul>
{/* 注冊路由 */}
<Switch>
<Route path="/home/news" component={News} />
<Route path="/home/message" component={Message} />
</Switch>
</div>
</div>
在這裡我們需要使用嵌套路由的方式,才能完成比對
首先我們得 React 中路由得注冊是有順序得,我們在比對得時候,因為 Home 元件是先注冊得,是以在比對的時候先去找 home 路由,由于是模糊比對,會成功的比對
在 Home 元件裡面去比對相應的路由,進而找到 /home/news 進行比對,是以找到 News 元件,進行比對渲染
如果開啟精确比對的話,第一步的 /home/news 比對 /home 就會卡住不動,這個時候就不會顯示有用的東西了!
6. 傳遞 params 參數
首先我們需要實作的效果是,點選消息清單,展示出消息的詳細内容
這個案例實作的方法有三種,第一種就是傳遞 params 參數,由于我們所顯示的資料都是從資料集中取出來的,是以我們需要有資料的傳輸給 Detail 元件
我們首先需要将詳細内容的資料清單,儲存在 DetailData 中,将消息清單儲存在 Message 的 state 中。
我們可以通過将資料拼接在路由位址末尾來實作資料的傳遞
<Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>
如上,我們将消息清單的 id 和 title 寫在了路由位址後面
這裡我們需要注意的是:需要采用模闆字元串以及 $ 符的方式來進行資料的擷取
在注冊路由時,我們可以通過 :資料名 來接收資料
<Route path="/home/message/detail/:id/:title" component={Detail} />
如上,使用了 :id/:title 成功的接收了由 Link 傳遞過來的 id 和 title 資料
這樣我們既成功的實作了路由的跳轉,又将需要擷取的資料傳遞給了 Detail 元件
我們在 Detail 元件中列印 this.props 來檢視目前接收的資料情況
我們可以發現,我們傳遞的資料被接收到了對象的 match 屬性下的 params 中
是以我們可以在 Detail 元件中擷取到又 Message 元件中傳遞來的 params 資料
并通過 params 資料中的 id 值,在詳細内容的資料集中查找出指定 id 的詳細内容
const { id, title } = this.props.match.paramsconst findResult = DetailData.find((detailObj) => { return detailObj.id === id})
采用 search 傳遞的方式,無需在 Route 中再次聲明,可以在 Detail 元件中直接擷取到
我們可以發現,我們的資料儲存在了 location 對象下的 search 中,是一種字元串的形式儲存的,我們可以引用一個庫來進行轉化 querystring
import qs from 'querystring'
這個庫是 React 中自帶有的,它有兩個方法,一個是 parse 一個是 stringify
我們可以采用 parse 方法,将字元串轉化為鍵值對形式的對象
const { search } = this.props.locationconst { id, title } = qs.parse(search.slice(1))
這樣我們就能成功的擷取資料,并進行渲染
tips:無需聲明接收
8. 傳遞 state 參數
采用傳遞 state 參數的方法,是我覺得最完美的一種方法,因為它不會将資料攜帶到位址欄上,采用内部的狀态來維護
<Link to={{ pathname: '/home/message/detail', state: { id: msgObj.id, title: msgObj.title } }}>{msgObj.title}</Link>
首先,我們需要在 Link 中注冊跳轉時,傳遞一個路由對象,包括一個 跳轉位址名,一個 state 資料,這樣我們就可以在 Detail 元件中擷取到這個傳遞的 state 資料
注意:采用這種方式傳遞,無需聲明接收
我們可以在 Detail 元件中的 location 對象下的 state 中取出我們所傳遞的資料
const { id, title } = this.props.location.state
const { id, title } = this.props.location.state || {}
直接使用即可~
解決清除緩存造成報錯的問題,我們可以在擷取不到資料的時候用空對象來替代,例如,
const { id, title } = this.props.location.state || {}
當擷取不到 state 時,則用空對象代替
這裡的 state 和狀态裡的 state 有所不同