天天看點

React 入門學習(十一)-- React 路由傳參

React 入門學習(十一)-- React 路由傳參

大家好,我是小丞同學,一名大二的前端愛好者

這篇文章是學習 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

React 入門學習(十一)-- React 路由傳參

我們發現它出現了兩個 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 檔案夾中。

React 入門學習(十一)-- React 路由傳參

我們有幾種方法,可以解決這個問題

将樣式引入的路徑改成絕對路徑

引入樣式檔案時不帶 .

使用 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 這樣就能夠實作我們想要的效果了

React 入門學習(十一)-- React 路由傳參

 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 參數

React 入門學習(十一)-- React 路由傳參

首先我們需要實作的效果是,點選消息清單,展示出消息的詳細内容

這個案例實作的方法有三種,第一種就是傳遞 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 來檢視目前接收的資料情況

React 入門學習(十一)-- React 路由傳參

我們可以發現,我們傳遞的資料被接收到了對象的 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 元件中直接擷取到

React 入門學習(十一)-- React 路由傳參

我們可以發現,我們的資料儲存在了 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      
React 入門學習(十一)-- React 路由傳參
const { id, title } = this.props.location.state || {}      

直接使用即可~

解決清除緩存造成報錯的問題,我們可以在擷取不到資料的時候用空對象來替代,例如,

const { id, title } = this.props.location.state || {}      

當擷取不到 state 時,則用空對象代替

這裡的 state 和狀态裡的 state 有所不同

繼續閱讀