React-Router基礎(三):嵌套路由,路由跳轉

接下來,我們就來講下嵌套路由。

這裏,我們仍然用上一篇博客的 demo 繼續做演示。

比如,我們現在需要有一個這樣的層級關係:

/                  首頁
/course            課程
/work              作品
    /js
    /node
        /express
        /koa
    /react

那麼我們先把文件創建好:

首先 Work.js 肯定是最主要的,其他都是它內部的東西。

接下來,就要在路由表裏面做文章了,整個嵌套路由,它裏面有一個最核心的事,這個你只要知道了,一切都沒問題。

那就是 <Route /> 這個路由節點,它可以出現在任何地方,任何一個組件裏面。

我們之前都放在 App.js 裏面,就是爲了看起來方便。

所以,在 Work.js 裏面,我們也可以寫:

然後我們就可以看到,二級導航OK了:

但是我們會發現,有個小問題,就是我們在代碼中寫了大量的 work:

那麼,萬一外面的路由,也就是 App.js 裏面的地址改了,那裏面是不是全得改?

而且如果你裏面還有三級,四級路由嵌套,那改動量就大了。所以任何一個製造耦合的機會,都是不好的。

我們希望的是,如果你要改,就只改這個文件,其他的文件一律不動。

那怎麼樣才能做到,外面的改了,裏面的自動變?

很簡單,我們要做的是獲取 this.props.match:

可以看到,這個 match 的 path 就是我們所需要的。

那麼,如果我們繼續點到 JS,Node,React 裏面去:

注意,這時候,path 還是 /work。

因爲我現在獲取的是我這層所匹配的東西,而不是在往裏一層。

所以你不用擔心,儘管地址真的已經變成了 /work/js,但是 match 打印出來的 path 還是 work。

因爲這個 match 的本意就是,符合我這級要求的路由信息。別的級別,裏面的我都不管。

所以我們最好是能做到這種解耦合的狀態,你別的組件想怎麼改隨便改,跟我沒關係,我這裏面的東西不用變:

所以三級路由導航我們也就知道怎麼寫了:

那麼如果結構是從數據庫裏面讀出來的,怎麼辦?

因爲 <Route /> 它跟普通的節點一樣,所以它也是可以循環出來的,並不是說它就一定得寫死在裏面。

所以,我們還可以做成無限層級嵌套路由。

首先,我們先還原到之前的一級菜單,只將 Work.js 保留下來,然後假設 courseData 裏面的多層級數據來自數據庫:

接下來,就是獲取路徑和數據,並渲染:

這樣,一個無限層級的嵌套路由就OK了:

所以嵌套路由的原理其實很簡單:在任何組件中,都能使用 Route,因爲整個 App 包含在 Router 中。

然後用 path 存儲當前的路由路徑,向後追加更多級別即可。

 

接下來,我們再來說下路由跳轉。

其實不管是 React 還是其他框架裏面,絕大多數的路由其實都是通過 history 來實現的。

history 本質上是一個棧。它的特點,就是後放進去的,最先出來。

類似於我們拿盤子,一疊盤子,我們都是從最上面開始拿,沒人從底下抽。而最上面的盤子,就是我們最後放進去的。

我們瀏覽器裏面的歷史記錄也是如此。

那麼當我們使用 Link 的時候,就需要用戶去點,因爲它是個按鈕,你要不點,就沒事發生。

而除了 Link,還有一個標籤 Redirect,它的意思就是重定向,它不需要用戶點,只要你在標籤裏面放了 Redirect,那麼這個頁面會自動跳走。

我們先將作品頁 Work.js 還原:

然後在 Index.js 裏面放上一個 Redirect 標籤,讓它自動跳轉到 /work:

然後我們刷新頁面,就可以看到,直接就進入了 /work 的路由:

可以看到,首頁點不進去。而且是直接跳轉到 /work 頁面的。你用盡一切辦法都進不了首頁的 /。

即使我們在地址欄上手動的刪掉 /work,在按回車,它還是會直接跳轉到 /work。

那麼 Redirect 它一般用在哪呢?比如用戶登錄:

只有登錄了,login 爲 true,纔可以進到首頁。

所以 Redirect 就是無條件跳轉。

然後我們雖然能用 Link,但其實我們平常用的 Link 並不是最完整的一個狀態,如果需要的話,其實是改它裏面的東西的。

我們平常在 Link 裏面用的 to,它後面的值就是一個字符串,其實這是個簡寫,它裏面還可以寫個 json。

這個 json 裏面可以帶幾個東西:

1,pathname。

2,search,就是問號後面那個東西

3,hash。

因爲我們現在用的就是 HashRouter 路由,所以 hash 測不出來,我們可以換成 BrowserRouter:

然後我們加上 pathname,search,hash 後,點擊首頁:

那麼如果我們就用 HashRouter,和 hash 配起來會怎麼樣呢?

其實並不會起衝突,只是會在後面又添了一個而已。

 

接下來,我們會了解一個比較重要的東西,如何通過 JS 來進行跳轉

首先,我們需要一個 history 對象。

length:50,代表的是我的 history 裏面已經堆了 50 個了。

push(xxx),字符串和 json 都可以。和 Link 裏面的 to 一樣。

go(num),代表的是前進或者後退多少級。

repleace(xxx),把當前的級別抹掉。和 push 裏面的參數是完全一致的。

 

比如現在,我想跳轉到某一個地方去,就需要 push 方法:

push 方法接收的參數是什麼?你在 Link 裏面的 to 怎麼寫,它裏面就怎麼寫。

 

然後,go,你給它的是個數字,比如 go(-1),那就是往回退一個。

goBack,就是 go(-1) 的簡稱。

goForward,就是 go(1) 的簡稱。

所以我們直接用 history 就行了。它裏面有各種各樣的方法。

 

然後,history 裏面有個 listen( function(){} ),就是監聽。如果你需要的話,就可以加個函數在裏面。只要它這個路由跳轉了,它就都會通知你,告知你用戶從哪來,到哪去。

當然在現在的 index.js 裏面不適用,因爲在 index.js 裏面,只要你一跳轉,你當前的這個組件就沒了,消失了。

那麼在哪個地方合適呢?在 Work.js,Course.js 裏面都合適,因爲在它跳轉的時候,主組件並不會消失,它還會在那,所以就可以用 listen。當然大部分情況下,我們也是用不到 listen 的。

 

然後我們來說下路由的 search 參數:

可以看到,match 裏面它是沒有 search 參數的。

search 你是不能直接的通過 match 來獲取的。因爲實際上來說,它這個參數並不是我們 Router 的一部分,相反,它是 location 的一部分。而 location 對象是 window 裏面自帶的。

因爲,我們現在用的是 hash 的模式。

在 hash 裏面,你的 search 其實不是一個真正的 search,它是仍在 hash 裏面的,所以 location 裏面的 search 是解析不出來的。

所以你要真想用 search 的話,我們是需要換成 BrowserRouter 的:

現在 search 裏面的參數,是需要我們自己去處理的,有一個方法,是原生 JS 裏面帶的:new URLSearchParams。

從它的名字就可以看出來,它是一個專門用來獲取你地址裏面 search 參數的東西。

它接收的是一個字符串,然後我們可以通過它的 get 方法來獲取

所以標準的 Router,是不認你的 search 參數的。它認的是它自己那套。

路由的跳轉並不難,但是你要如何在真實的項目當中,把它給用起來,這就是一個重要的事了。

 

最後,我們總結一下關於路由跳轉的問題:

本質上,路由都是通過 history 實現的,而 history 本質上是一個棧,所以,總共有兩套方法來操作:

1,push、pop:向棧尾添加 / 從棧尾取出。

2,replace:直接替換掉當前級別。

 

Link 標籤,相當於 push 操作,類似於 a 鏈接。如:

<Link to="xxx">文字</Link>

或者更復雜的

<Link to={{
    pathname: '/work',
    search: '?a=12&b=5',
    hash: '#123'
}}>文字</Link>

 

Redirect 標籤,相當於 replace 操作,類似於 302。如:

<Redirect to="xxx">文字</Redirect>

或者更復雜的

<Redirect to={{
    pathname: '/work',
    search: '?a=12&b=5',
    hash: '#123'
}}>文字</Redirect>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章