一文帶你學懂React前端路由😃

這是我參與8月更文挑戰的第3天,活動詳情查看:8月更文挑戰css

React路由

SPA

即單頁面web(single page web application)應用。整個應用只有一個完整的頁面,點擊頁面中的連接不會刷新頁面,只會作頁面的局部更新。數據都須要經過ajax獲取。html

也就是說,正由於有了路由這個技術的存在,才能實現咱們在同一個頁面中進行局部刷新(單頁面多組件)。前端

路由的理解

  • 一個路由就是一個映射關係(key: value)node

  • key爲路徑,value多是function(後端路由) 或 component(前端路由);react

  • 後端路由:註冊:router.get(path, function(req, res))。當node接收到一個請求時,根據請求路徑找到匹配的路由,調用路由中的函數來處理請求,返回響應數據。web

  • 前端路由:註冊:Route path="/test" component={Test}。用於展現頁面內容。當瀏覽器的path變爲/test時,當前路由組件就會變成Test組件。好比對於一個在127.0.0.1:3000的頁面,當它爲127.0.0.1:3000/home(而不是/home.html)顯示的就是home組件。ajax

  • 好比下圖這個案例,切換的就是頁面,而不是組件。(下面會有此案例同個頁面多個組件的寫法)後端

    luyou_03.gif

首先要認識一下react的一個的插件庫react-router-dom(須要手動下載),該庫專門用來實現一個SPA應用,基於react的項目基本都會用到它。瀏覽器

前端路由

1、路由的基本使用

歷史記錄 (前端路由基礎)

在咱們以前的學習BOM中,是有一個history方法的,在這裏咱們經過引入一個historyjs文件直接調用歷史記錄的一些方法。瀏覽器的歷史記錄是一個棧的結構。markdown

<script src="https://cdn.bootcss.com/history/4.7.2/history.js"></script>
let history = History.createBrowerHistory();  // 直接使用H5推出的history的API
// let history = History.createBrowerHistory();   hash值 錨點跳轉(多了個#)
function push(path) {
    history.push(path);   // 入棧
}
function replace(path) {
    history.replace(path);  // 替代棧頂元素
}
function back() {
    history.goBack();   // 回退
}
function forward() {
    history.goForward();   // 前進
}
history.listen(location)=> {  // 監聽路徑變化
    console.log(location);
}
複製代碼

案例

接下來實現上面那個案例。在原生js中是經過<a>標籤跳轉到不一樣的頁面,而在react中,是靠路由連接<Link><link/>實現切換組件的(編寫路由連接)。注意:這裏的Link是從react-router-dom庫裏面拿的。在組件分別展現的時候須要註冊路由route

基本步驟:(1)確認界面中的導航區、展現區;(2)導航區的a標籤改成Link標籤;(3)展現區的Route標籤進行路徑的匹配;(4)在<App>的最外側包裹一個<BrowserRouter>或者<HashRouter>

// App.jsx
import { Link, BrowserRouter, Route } from 'react-router-dom'  // 引入react-router-dom庫
// 編寫路由連接
<Link className="list-group-item" to="/about">About</Link>
<Link className="list-group-item" to="/home">Home</Link>
// 註冊路由
<Route path="/about" component={About}></Route>
<Route path="/home" component={Home}></Route>
複製代碼

路由在使用的時候,須要在外層中包裹一層<BrowserRouter><BrowserRouter/>,至關於一個路由器,管理裏面的東西。並且只能有一個路由器,不能寫2個,不然就至關於兩個路由器,兩個路由器之間是沒有數據溝通的。所以能夠在App組件渲染的時候,在其外層放路由器。即

// index.js
ReactDOM.render(
    <BrowserRouter>        <App />    </BrowserRouter>,
    document.getElementById('root')
);
複製代碼

這樣子就能夠實現一個SPA了。此時能夠看到頁面路徑發生了變化,並且<Link>標籤渲染到瀏覽器中實際上是轉換爲<a>標籤的,而to轉換爲href(轉換爲瀏覽器認識的標籤)。可是是組件的展現而不是頁面之間的跳轉(沒有.html後綴),打開控制檯的network也能夠看到此時的瀏覽器並無發送請求。

luyou2_03.gif

若是想要加上上面那個案例的高亮效果,把Link改爲NavLink便可(記得從react-router-dom中引入)。默認點擊的時候默認給active樣式,可是若是想要給的樣式名不是active,那就須要加一個activeClassName="..."(這個的默認值是active)

<NavLink activeClassName="home" className="list-group-item" to="/home">Home</NavLink>
//至關於
<NavLink activeClassName="home" className="list-group-item" to="/home" children="Home"></NavLink>
複製代碼

總結:NavLink能夠實現路由連接的高亮,經過activeClassName指定樣式名,標籤體內容是一個特殊的標籤屬性,經過this.props.children能夠獲取到標籤體內容。

上面這種組件就是路由組件,那麼它和普通組件還有什麼區別呢?

  • 寫法不一樣。通常組件:直接寫組件標籤:<home/>

    路由組件:<Route path="/about" component={Home}></Route>

  • 存放位置不一樣。通常組件放在components;路由組件通常放在pages中。

  • 接收到的props不一樣。通常組件:給它傳遞什麼就收到什麼;路由組件:接收到3個固定屬性

對於路由組件,咱們打印出它的props屬性,這裏在用這個組件的時候並無給它傳值,可是它會有自帶的propshistorylocationmatch)其中history.location=location。而對於普通組件,若是沒有給它傳值,它打印出來的props就是空的。

props.png 上面說的是路由的基礎使用,接下來講一說在路由中是怎麼進行組件之間的傳參的。

2、向前端路由傳遞參數

  1. 傳遞params參數

    在路由組件傳遞參數的時候,在Link中傳遞參數,要在註冊的路由將這些參數讓Detail接收,採用下面這種方式。此時在Detail組件中打印this.props的話就能夠在this.props.match.params裏面看到咱們經過Link傳遞過去的參數。

    <Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>
    <Route path="/home/message/detail/:id/:title" component={Detail}></Route>
    複製代碼
  2. 傳遞search參數

    search參數在傳遞的時候形式以下。並且search不用在註冊路由的時候接收參數,直接註冊便可,在this.props.location.search中就能夠找到傳遞的參數,不過在這裏傳遞的對象是?key=value&key=value,咱們要手動改爲{key: value;}的形式;

    可使用引入內置庫import qs from queryString,再用qs.parse(search)來處理從this.props中獲得的search對象(注意:用parse以後前面仍是會有一個?,用slice(1)截掉便可

    <Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>
    複製代碼
  3. state參數

    上面說的params參數和search參數在傳遞參數的時候都會將傳遞的鍵值對暴露在地址欄上;state和search同樣,不用聲明接收,直接註冊便可;傳遞參數方式以下(傳對象);

    傳遞以後在this.props.location.state裏面就能夠找到所傳遞的參數;注意:路由中的state跟組件中的state是不同的;state參數只是路由中的一個屬性,跟組件裏面的state的沒有關係

    <Link to={{pathname='/home/message/detail', state:{id:msgObj.id,title:msgObj.title}}}></Link>
    複製代碼

    用state傳遞參數的話刷新也能夠保留參數。此時雖然參數沒有在地址欄,可是也不會丟失,由於在這裏用BrowserRouter來管理路由的,它一直在維護瀏覽器的historyhistory把傳遞的東西記下了,所以不會丟失。

3、補充知識點..

路由的模糊匹配與精確匹配

  • 模糊匹配: 【輸入的路徑】必須包含【匹配的路徑】,且順序要一致。好比把to後面的連接改爲home/a/b時,在找home的路由的時候,會先匹配前面的home,匹配到了就找到了。這就是模糊匹配,且默認就是默認匹配。
  • 嚴格匹配:能夠經過exact={true}exact來開啓嚴格匹配

通常狀況下咱們不開啓嚴格匹配,由於有時候開啓嚴格匹配會致使沒法繼續匹配二級路由

// 編寫路由連接 輸入的路徑
<Link to="/home/a/b">Home</Link>
// 註冊路由 匹配的路徑
<Route exact={true} path="/home" component={Home}></Route>
複製代碼

Switch組件和Redirect組件

提升效率:Switch組件。以下代碼,經過/home匹配到Home組件以後就不會繼續匹配下去了。不然test組件也會被展現在頁面中。注意:要從react-router-dom中引入SwitchRedirectreact-router-dom裏面的一個內置組件,會讓剛刷新瀏覽器的時候,默認跳轉到指定組件。(通常寫在全部路由註冊的最下方,當全部路由都沒法匹配時,跳轉到Redirect指定的路由)

<Switch>
    <Route path="/about" component={About}></Route>
    <Route path="/home" component={Home}></Route>
    <Route path="/home" component={test}></Route>
    <Redirect to="/home"/>
</Switch>
複製代碼

嵌套組件

  • 註冊子路由的時候要寫上父路由的path值
  • 路由的匹配是按照註冊路由的順序進行的

通常狀況下咱們不會讓同一個路徑去對應展現多個組件,若是出現這種狀況的話就可使用Switch。一般狀況下,path和component是一一對應的關係,Switch能夠提升路由匹配效率(單一匹配)。

加油!

相關文章
相關標籤/搜索