無廢話快速上手React路由
本文以簡潔為目標,幫助快速上手react-router-dom
預設你接觸過路由相關的開發
安裝
輸入以下命令進行安裝:
// npm npm install react-router-dom // yarn yarn add react-router-dom
react-router相關標籤
react-router
常用的元件有以下八個:
import { BrowserRouter,HashRouter,Route,Redirect,Switch,Link,NavLink,withRouter,} from 'react-router-dom'
簡單路由跳轉
實現一個簡單的一級路由跳轉
import { BrowserRouter as Router,Link } from 'react-router-dom' import Home from './home' import About from './about' function App() { return ( <div className="App"> <Router> <Link to="/home" className="link">跳轉Home頁面</Link> <Link to="/about" className="link">跳轉About頁面</Link> <Route path="/home" component={Home}/> <Route path="/about" component={About}/> </Router> </div> ); } export default App;
效果如下:
要點總結:
Route
元件必須在Router
元件內部Link
元件的to
屬性的值為點選後跳轉的路徑Route
組建的path
屬性是與Link
標籤的to
屬性匹配的;component
屬性表示Route
元件匹配成功後渲染的元件物件
巢狀路由跳轉
React
的路由匹配層級是有順序的
例如,在 App
元件中,設定了兩個路由元件的匹配路徑,分別是 /home
和 /about
,程式碼如下:
import { BrowserRouter as Router,} from 'react-router-dom' import Home from './home' import About from './about' function App() { return ( <div className="App"> <Router> <KndqqfJHpLink to="/home">跳轉Home頁面</Link> <Link to="/about">跳轉About頁面</Link> <Route path="/home" component={Home}/> <Route path="/about" component={About}/> </Router> </div> ); } export default App;
然後 Home
元件中同樣也想設定兩個路由元件的匹配路徑,分別是 /home/one
和 /home/two
,此時就可以看出,這個 /home/one
和 /home/two
為上一級路由 /home
的二級巢狀路由,程式碼如下:
import React from 'react' import { Route,} from 'react-router-dom' import One from './one' import Two from './two' function Home () { return ( <> 我是Home頁面 <Link to="/home/one">跳轉到Home/one頁面</Link> <Link to="/home/two">跳轉到Home/two頁面</Link> <Route path="/home/one" component={One}/> <Route path="/home/two" component={Two}/> </> ) } export default Home
特別注意: Home
元件中的路由元件 One
的二級路由路徑匹配必須要寫 /home/one
,而不是 /one
,不要以為 One
元件看似在 Home
元件內就可以簡寫成 /one
動態連結
NavLink
可以將當前處於active
狀態的連結附加一個active
類名,例如:
import { BrowserRouter as Router,NavLink } from 'react-router-dom' import Home from './home' import About from './about' function App() { return ( http://www.cppcns.com <div className="App"> <Router> <NavLink to="/home" className="link">跳轉Home頁面<程式設計客棧;/NavLink> <NavLink to="/about" className="link">跳轉About頁面</NavLink> <Route path="/home" component={Home}/> <Route path="/about" component={About}/> </Router> </div> ); } export default App; /* 設定active類的樣式 */ .active { font-weight: blod; color: red; }
效果如下:
路由匹配優化
當點選跳轉連結時,會自動去嘗試匹配所有的Route
對應的路徑,如圖所示:
正常情況下,只需匹配到一個規則,渲染即可,即匹配成功一個後,無需進行後續的匹配嘗試,此時可以用Switch
元件,如下所示:
import {
BrowserRouter as Router,} from 'react-router-dom'
import Home from './home'
import About from './about'
function App() {
return (
程式設計客棧 <div className="App">
<Router>
<NavLink to="/home" className="link">跳轉Home頁面</NavLink>
<NavLink to="/about" className="link">跳轉About頁面</NavLink>
<Switch>
<Route path="/home" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/home" component={Home}/>
<Route path="/home" component={Home}/>
{/* 此處省略一萬個Route元件 */}
<Route path="/home" component={Home}/>
</Switch>
</Router>
</div>
);
}
export default App;
效果如下:
要點總結:
將多個Route
元件同時放在一個Switch
元件中,即可避免多次無意義的路由匹配,以此提升效能
重定向
當頁面跳轉時,若跳轉連結沒有匹配上任何一個 Route
元件,那麼就會顯示 404
頁面,所以我們需要一個重定向元件 Redirect
,程式碼如下:
import { BrowserRouter as Router,} from 'react-router-dom' import Home from './home' import About from './about' function App() { return ( <div className="App"> <Router> <NavLink to="/home" className="link">跳轉Home頁面</NavLink> <NavLink to="/about" className="link">跳轉About頁面</NavLink> <NavLink to="/shop" className="link">跳轉Shop頁面</NavLink> {/* 點選,跳轉到/shop,但該路徑沒有設定 */} <Switch> <Route path="/home" component={Home}/> <Route path="/about" component={About}/> <Redirect to="/home" /> {/* 當以上Route元件都匹配失敗時,重定向到/home */} </Switch> </Router> </div> ); } export default App;
效果如下:
路由傳參
所有路由傳遞的引數,都會在跳轉路由元件的 props
中獲取到,每種傳參方式接收的方式略有不同
路由傳參的方式一共有三種,依次來看一下
第一種
第一種是在 Link
元件的跳轉路徑上攜帶引數,並在 Route
元件的匹配路徑上通過 :引數名
的方式接收引數,程式碼如下:
import { BrowserRouter as Router,} from 'react-router-dom' import Home from './home' import About from './about' function App() { return ( <div className="App"> <Router> {/* 在 /home 的路徑上攜帶了 張三、18 共兩個引數 */} <NavLink to="/home/張三/18" className="link">跳轉Home頁面</NavLink> <NavLink to="/about" className="link">跳轉About頁面</NavLink> <Switch> {/* 在 /home 匹配路徑上相同的位置接收了 name、age 兩個引數 */} <Route path="/home/:name/:age" component={Home}/> <Route path="/about" component={About}/> </Switch> </Router> </div> ); } export default App;
嘗試跳轉,並列印一下路由元件的 props
可以看到,第一種方式的引數是通過 props.match.params
來獲取的
第二種
第二種方式就是通過在 Link
元件的跳轉連結後面跟上以 ?
開頭,類似 ?a=1&b=3
這樣的引數進行傳遞,程式碼如下:
import { BrowserRouter as Router,} from 'react-router-dom' import Home from './home' import About from './about' function App() { return ( <div className="App"> <Router> {/* 在跳轉路徑後面以?開頭傳遞兩個引數,分別為name=張三、age=18 */} <NavLink to="/home?name=張三&age=18" className="link">跳轉Home頁面</NavLink> <NavLink to="/about" className="link">跳轉About頁面</NavLink> <Switch> {/* 此處無需做接收操作 */} <Route path="/home" component={Home}/> <Route path="/about" component={About}/> </Switch> </Router> </div> ); } export default App;
嘗試跳轉,並列印一下路由元件的 props
可以看到,第二種方式的引數是通過 props.location.search
來獲取的,不過這裡的引數需要自己簡單做進一步轉化,這裡就不做過多說明了
第三種
第三種方式就是以物件的形式編寫 Link
元件的 to
跳轉屬性,並通過 state
屬性來傳遞引數,程式碼如下:
import { BrowserRouter as Router,} from 'react-router-dom' import Home from './home' import About from './about' function App() { return ( <div className="App"> <Router> {/* 以物件的形式描述to屬性,路徑屬性名為pathname,引數屬性名為state */} <NavLink to={{pathname: "/home",state: {name: '張三',age: 18}}} className="link">跳轉Home頁面</NavLink> <NavLink to="/about" className="link">跳轉About頁面</NavLink> <Switch> {/* 此處無需特地接收屬性 */} <Route path="/home" component={Home}/> <Route path="/about" component={About}/> </Switch> </Router> </div> ); } export default App;
嘗試跳轉,並列印一下路由元件的 props
可以看到,第三種方式的引數是通過 props.location.state
來獲取的
函式式路由
以上主要都是通過 react-router-dom
中的 Link
元件來往某個路由元件跳轉
但有時,我們需要更靈活的方式進行跳轉路由,例如通過呼叫一個函式,隨時隨地進行路由跳轉,這就叫函式式路由
函式式路由用到的方法有以下 5
個(下方截圖來自路由元件的 props
)
5
個方法分別是 push
、replace
、goForward
、goBack
、go
,接下來按順序介紹一下這幾個方法
push
push
方法就是使頁面跳轉到對應路徑,並在瀏覽器中留下記錄(即可以通過瀏覽器的回退按鈕,返回上一個頁面)
舉個例子:在路由元件 Home
中設定一個按鈕 button
,點選後呼叫 push
方法,跳轉到 /about
頁面
import React from 'react' function Home (props) { let pushLink = () => { props.history.push('/about') } return ( <div className="a"> 我是Home頁面 <button onClick={pushLink}>跳轉到about頁面</button> </div> ) } export default Home
跳轉效果如下:
可以看到,通過 push
方法跳轉以後,可以通過瀏覽器的回退按鈕,返回上一個頁面
replace
replace
方法與 push
方法類似,不一樣的地方就是,跳轉後不會在瀏覽器中儲存上一個頁面的記錄(即無法通過瀏覽器的回退按鈕,返回上一個頁面)
改動一下程式碼
import React from 'react' function Home (props) { let replaceLink = () => { props.history.replace('/about') } return ( <div className="a"> 我是Home頁面 <button onClick={replaceLink}>跳轉到about頁面</button> </div> ) } export default Home
跳轉效果如下:
可以看到,剛開始的路徑程式設計客棧是 ‘/' ,然後跳轉到 ‘/home' ,再點選按鈕,通過 replace
方法跳轉到 /about
頁面。最後通過瀏覽器的回退按鈕返回到了 /
頁面,說明中間的 /home
沒有被存在瀏覽器的記錄裡
goForward
呼叫 goForward
方法,就相當於點選了瀏覽器的返回下一個頁面按鈕,如下圖所示:
這裡就不做過多演示了
goBack
呼叫 goBack
方法,就相當於點選了瀏覽器的返回上一個頁面的按鈕,如下圖所示:
go
go
方法顧名思義,是用於跳轉到指定路徑的。
該方法接受一個引數(引數型別為 Number
),情況如下:
- 當引數為正數
n
時,表示跳轉到下n
個頁面。例如go(1)
相當於呼叫了一次goForward
方法 - 當引數為負數
n
時,表示跳轉到上n
個頁面。例如go(-3)
相當於呼叫了三次goBack
方法 - 當引數為
0
時,表示重新整理當前頁面
普通元件使用路由
這裡區分兩個概念,分別為 普通元件 和 路由元件
通過 Route
元件渲染的元件為路由元件 ,其餘的基本上都為 普通元件
例如,下方程式碼中:Home
元件為路由元件 ; App
元件為普通元件
import { BrowserRouter as Router,} from 'react-router-dom' import Home from './home' export default function App() { return ( <div className="App"> <Router> <NavLink to='/home' className="link">跳轉Home頁面</NavLink> <Switch> <Route path="/home" component={Home}/> </Switch> </Router> </div> ); }
然後,路由元件跟普通元件最大的區別就是,元件的 props
屬性中是否有下圖所示的內容:(前者有,後者無)
此時,react-router-dom
提供了一個 withRouter
方法,可以使普通元件也能像路由元件一樣有那些方法或資料可以使用
使用方法如下:
import { BrowserRouter as Router,// 1. 引入 witRouter } from 'react-router-dom' import About from './about' function App(props) { console.log(props); // 3. 嘗試列印普通元件App的props,發現此時props中已有內容了,即普通元件也能擁有跟路由元件一樣類似的功能 return ( <div className="App"> <Router> <NavLink to="/about" className="link">跳轉About頁面</NavLink> <Switch> <Route path="/about" component={About}/> </Switch> </Router> </div> ); } export default withRouter(App); // 2. 通過withRouter方法對普通元件做一層包裝處理
補充
replace
在函式式路由裡跳轉型別主要有兩種,分別是 push
和 replace
,那麼在非函式式路由中,同樣也可以自定義跳轉型別,具體的實現程式碼如下:
import { BrowserRouter as Router,Link } from 'react-router-dom' import Home from './home' import About from './about' function App() { return ( <div className="App"> <Router> <Link to="/home" className="link">跳轉Home頁面</Link> <Link to="/about" className="link">跳轉About頁面</Link> <Route path="/home" component={Home} replace={true}/> {/* replace為true,跳轉型別為replace */} <Route path="/about" component={About} replace={false}/> {/* replace為false,跳轉型別為push */} </Router> </div> ); } export default App; Route` 元件上有個 `replace` 屬性可以設定跳轉型別,當值為 `true` 時,跳轉型別為 `replace` ; 為 `false` 時,跳轉型別為 `push
excat
路由的匹配預設是模糊匹配的,舉個例子:
import { BrowserRouter as Router,} from 'react-router-dom' import Home from './home' import About from './about' function App() { return ( <div className="App"> <Router> <Link to="/home/abc">跳轉Home頁面</Link> {/* 跳轉到/home/abc,但實際home下沒有abc這個路由元件 */} <Link to="/about/abc">跳轉About頁面</Link> {/* 跳轉到/about/abc,但實際home下也沒有abc這個路由元件 */} <Route path="/home" component={Home} /> {/* 路由匹配規則為/home,沒有設定exact屬性,當前為模糊匹配 */} <Route path="/about" component={About} exact/> {/* 路由匹配規則為/about,設定了exact屬性,當前為精準匹配 */} </Router> </div> ); } export default App;
效果如下:
圖中看出,因為跳轉 /home/abc
時,第一個 Route
元件是模糊匹配的,所以先匹配到了 /home
,因此 Home
元件渲染了 ; 而跳轉 /about/abc
時,第二個 Route
元件是精準匹配的,即 /about/abc
不等於 /about
,所以 About
元件也沒有渲染
總結:
- 如果想要精準匹配的話,只需要將
Route
元件的exact
屬性設定為true
即可 - 精準匹配要謹慎使用,因為可能會影響巢狀路由的使用
以上就是無廢話快速上手React路由的詳細內容,更多關於React路由快速上手的資料請關注我們其它相關文章!