react-router-dom的使用說明
React-Router-Dom
1. React-Router
react-router是一個核心庫,我們在做PC端時要用react-router-dom,而在移動端我們要用React-Router-Native
2.React-Router-Dom
這個庫是專門做PC端的路由
- 2.1 在React-cli項目中安裝React-Router-Dom
npm i react-router-dom
- 2.2 注意
React-Router-Dom最新版本是6,如果下載指定版本加@符
npm i react-router-dom@5
3.React-Router-Dom5
- 3.1 React-Router-Dom的意義
前端路由存在的意義就是單頁面應用,英文:Single Page Application,前端有自己的一套路由,頁面只有一個html完成,在不同的路徑下,加載不同的組件,從而完成單頁面應用,在此也可以通過ajax請求的方式去后端獲得數據
- 3.2 注意
React-Router-Dom6在2021年11月已成為默認版本
4.React-Router-Dom5基本使用
- 4.1 link和Route
import {Link, Route} from "react-router-dom" <Link to="/about">About</Link> <Link to='/home'>Home</Link> <Switch> <Route path="/about" component={About}/> <Route path="/home" component={Home}/> <Redirect to="/about"/> </Switch>
link要和Route相互搭配,link書寫鏈接,由Route來注冊路由
- 4.2 BrowserRouter
在react中我們要用BrowserRouter包裹一下路由,通常在index.js里
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; import {BrowserRouter} from "react-router-dom" const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <BrowserRouter> <App/> </BrowserRouter> </React.StrictMode> ); reportWebVitals();
- 4.3 HashRouter
和BrowserRouter一樣,只不過HashRoute在url里是有hash值的
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; import {HashRouter} from "react-router-dom" const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <HashRouter> <App/> </HashRouter> </React.StrictMode> ); reportWebVitals();
- 4.4 Switch
在React中相同路徑下是可以加載多個組件的,假如你不想,你可以用Switch包裹一下Route,這樣即使相同路徑下,也只是加載最上面的組件
<Switch> <Route path="/home/news" component={News}/> <Route path="/home/massage" component={Message}/> <Route path="/home/massage" component={Detail}/> <Redirect to="/home/news"/> </Switch>
上面相同路徑但只加載Message組件
- 4.5 Redirect
在react中我們想在一開始默認加載哪個組件或者路徑不適配的時候我們可以用Redirect標簽,可以給我們重定向加載任何一個組件,但Redirect一般出現在Route的最下面
<Switch> <Route path="/home/news" component={News}/> <Route path="/home/massage" component={Message}/> <Redirect to="/home/news"/> </Switch>
5.路由的嵌套
- 5.1 NavLink組件
假設現在我們需要給予選中路由一個高亮我們可以使用NavLink標簽,我們可以把他單獨封裝成一個公用的路由組件
import React, {Component, Fragment} from "react" import {NavLink} from 'react-router-dom' import "./MyNavLink.css" export default class MyNavLink extends Component { render() { return ( <Fragment> <div className="btn-div"> <NavLink activeClassName="active" className="btn-a" {...this.props}/> </div> </Fragment> ) } }
注意高亮默認在React-Router中式action屬性
- 5.2 路由的嵌套
如果我們想在react項目中,寫入多級路由的話,我們需要在Link,Route以及Redirect中加入父級路由
5.2.1 父級路由組件
import {Fragment} from "react" import {Route, Switch, Redirect} from "react-router-dom" import Title from "./component/Title"; import About from "./pages/About"; import Home from "./pages/Home"; import MyNavLink from "./MyNavLink"; import './App.css'; function App() { return ( <Fragment> <Title/> <MyNavLink to="/about">About</MyNavLink> <MyNavLink to='/home'>Home</MyNavLink> <Switch> <Route path="/about" component={About}/> <Route path="/home" component={Home}/> <Redirect to="/about"/> </Switch> </Fragment> ); } export default App;
5.2.2 子級路由組件
import React, {Component, Fragment} from "react" import {Switch, Route, Redirect} from 'react-router-dom' import MyNavLink from "../../MyNavLink"; import Message from "./Message"; import News from "./News"; export default class Home extends Component { render() { return ( <Fragment> <h1>我是Home</h1><br/> <MyNavLink to="/home/news">News</MyNavLink> <MyNavLink to="/home/massage">Massage</MyNavLink> <Switch> <Route path="/home/news" component={News}/> <Route path="/home/massage" component={Message}/> <Redirect to="/home/news"/> </Switch> </Fragment> ) } }
- 5.3 路由的匹配
5.3.1路由的模糊匹配
<Fragment> <Title/> <MyNavLink to="/about">About</MyNavLink> <MyNavLink to='/home/a/b'>Home</MyNavLink> <Switch> <Route path="/about" component={About}/> <Route path="/home" component={Home}/> <Redirect to="/about"/> </Switch> </Fragment>
像這樣的路由我們多傳,雖然路徑不匹配但在模糊匹配下可以讓react渲染Home組件,但是不可以頭路徑不正確
例如:
<Fragment> <Title/> <MyNavLink to="/about">About</MyNavLink> <MyNavLink to='/a/home'>Home</MyNavLink> <Switch> <Route path="/about" component={About}/> <Route path="/home" component={Home}/> <Redirect to="/about"/> </Switch> </Fragment>
這樣前面的路徑不對是匹配不到的
5.3.2路由的嚴格匹配
假如現在我們不希望進行模糊匹配,嚴格按照路徑的話我們就可以開啟嚴格匹配模式
<Fragment> <Title/> <MyNavLink to="/about">About</MyNavLink> <MyNavLink to='/a/home'>Home</MyNavLink> <Switch> <Route exact={true} path="/about" component={About}/> <Route exact path="/home" component={Home}/> <Redirect to="/about"/> </Switch> </Fragment>
5.3.3 注意
我們不可以過多的使用嚴格模式就像ref一樣,否則會造成一些問題,并且在多級路由的父路由不可以開啟嚴格模式
6. 路由的參數
- 6.1 Params參數
6.1.1 傳遞Params參數
this.state.massageArr.map(item => { return <li key={item.id}> <Link to={`/home/massage/detail/${item.id}/${item.title}`}> {item.title} </Link> </li> })
我們通過數組的映射以及母版字符串的方式傳遞了兩個Params參數
6.1.2 接收Params參數
<Route path="/home/massage/detail/:id/:title" component={Detail}/>
這樣接收react-router幫我們生成了對象
6.1.3調用Params參數
export default class Detail extends Component { render() { const {id, title} = this.props.match.params const findResult = data.find((_item) => { return _item.id === id }) return ( <Fragment> <ul> <li>id:{id}</li> <li>title:{title}</li> <li>content:{findResult.content}</li> </ul> </Fragment> ) } }
我們可以通過props里面的match里面封裝的params里面將傳遞的值解構出來使用
- 6.2 Search參數
6.2.1 傳遞Search參數
this.state.massageArr.map(item => { return <li key={item.id}> <Link to={`/home/massage/detail?id=${item.id}&title=${item.title}`}> {item.title} </Link> </li> })
同樣我們也傳遞了兩個Search參數,但注意Search參數不需要接收
6.2.2 querystring庫
6.2.2.1 urlencoded編碼
key=value&key=value
像這樣的編碼格式被稱為urlencoded編碼格式
6.2.2.2 利用 querystring轉化格式
我們可以轉化
import qs from "querystring" qs.stringify() 將對象轉化為urlencoded qs.parse() 將urlencoded轉化為js中的對象
6.2.3 調用Search參數
import React, {Component, Fragment} from "react" import qs from "querystring" const data = [ {id: "01", content: "你好,寧夏"}, {id: "02", content: "你好,吉林"}, {id: "03", content: "你好,陜西"}, ] export default class Detail extends Component { render() { const {search} = this.props.location const {id, title} = qs.parse(search.slice(1)) const findResult = data.find((_item) => { return _item.id === id }) return ( <Fragment> <ul> <li>id:{id}</li> <li>title:{title}</li> <li>content:{findResult.content}</li> </ul> </Fragment> ) } }
6.2.4 注意
如果沒有這個第三方庫我們可以安裝
npm i querystring
- 6.3 state參數
6.3.1 傳遞state參數
this.state.massageArr.map(item => { return <li key={item.id}> <Link to={{pathname: "/home/massage/detail", state: {id: item.id, title: item.title}}}> {item.title} </Link> </li> })
傳遞state對象,要把地址和state封裝成一個對象
6.3.2 調用state參數
import React, {Component, Fragment} from "react" const data = [ {id: "01", content: "你好,寧夏"}, {id: "02", content: "你好,吉林"}, {id: "03", content: "你好,陜西"}, ] export default class Detail extends Component { render() { const {id, title} = this.props.location.state const findResult = data.find((_item) => { return _item.id === id }) return ( <Fragment> <ul> <li>id:{id}</li> <li>title:{title}</li> <li>content:{findResult.content}</li> </ul> </Fragment> ) } }
7.編程式路由導航
- 7.1 編程式路由導航的分類
push是壓棧式的,瀏覽器可以回退,有保存記錄。而replace是覆蓋瀏覽器的棧頂不能回退
- 7.2 replace編程式路由導航
replaceShow = (id, title) => { this.props.history.replace(`/home/massage/detail/${id}/${title}`) }
注意:只有在路由組件內才可以拿到這兩個方法
- 7.3 push編程式路由導航
pushShow = (id, title) => { this.props.history.push(`/home/massage/detail/${id}/${title}`) }
8. withRouter
如果我們想在非路由組件里調用路由組件的方法我們就可以用withRouter
import React, {Component, Fragment} from "react" import {withRouter} from "react-router-dom" class Title extends Component { back = () => { this.props.history.goBack() } forWord = () => { this.props.history.goForward() } render() { return ( <Fragment> <h2 style={{marginLeft: "50px"}}>React Router Demo</h2> <button onClick={this.forWord}>前進</button> <button onClick={this.back}>后退</button> <hr/> </Fragment> ) } } export default withRouter(Title)
注意:goBack為歷史記錄的后退,而goForward為前進,兩個函數后可以在路由組件找到
9. React-Router-Dom6
安裝
npm i react-router-dom@6
- 9.1 概述
內置組件以及寫法有些改變,函數式組件被官方明確推薦,又新增10個hooks
- 9.2 改變
9.2.1 刪除Switch,新增Routes
import {NavLink, Routes, Route} from "react-router-dom" <Routes> <Route path="/about" element={<About/>}/> <Route path="/home" element={<Home/>}/> </Routes>
9.2.2 重定向
import {NavLink, Routes, Route} from "react-router-dom" <Routes> <Route path="/about" element={<About/>}/> <Route path="/home" element={<Home/>}/> <Route path="/" element={<Navigate to="/about"/>}/> </Routes>
9.2.3 NavLink高亮
<NavLink to="/about" className={({isActive}) => isActive ? "list-group-item active":"list-group-item"}>About</NavLink>
在react-router-dom6中可以用函數的方式返回出樣式
9.2.4 路由表
import {NavLink, useRoutes} from "react-router-dom" const element = useRoutes(route)
我們可以通過路由表的方式生成路由
import About from "../pages/About"; import Home from "../pages/Home"; import {Navigate} from "react-router-dom"; export const route = [ { path: "/about", element: <About/> }, { path: "/home", element: <Home/> }, { path: "/", element: <Navigate to="/about"/> } ]
9.2.5 Outlet
多級路由也可以寫在路由表里,但是需要Outlet配合,類似Vue的roter-view
多級路由的路由表
import About from "../pages/About"; import Home from "../pages/Home"; import Message from "../pages/Message"; import News from "../pages/News"; import {Navigate} from "react-router-dom"; export const route = [ { path: "/about", element: <About/> }, { path: "/home", element: <Home/>, children: [ { path: "news", element: <News/> }, { path: "message", element: <Message/> } ] }, { path: "/", element: <Navigate to="/about"/> } ]
子路由可以用children來寫,類型也是數組,注意路徑不要加 “/”
Outlet是子路由的出口
import React, {Fragment, useState} from "react" import {Navigate,Outlet,NavLink} from "react-router-dom" export default function Home() { const [sum, setSum] = useState(1) return ( <Fragment> <h3>Home</h3> {sum === 2 ? <Navigate to="/about"/> : <h4>當前sum為{sum}</h4>} <button onClick={() => setSum(sum + 1)}>點我加一</button> <NavLink to="message">message</NavLink> <NavLink to='news'>news</NavLink> <Outlet/> </Fragment> ) }
- 9.3 Params參數
9.3.1 傳遞Params參數
import React, {Fragment, useState} from "react" import {Link, Outlet} from "react-router-dom" export default function Message() { const [message] = useState([ {id: "001", title: "消息1", content: "鋤禾日當午"}, {id: "002", title: "消息2", content: "汗滴禾下土"}, {id: "003", title: "消息3", content: "誰知盤中餐"}, {id: "004", title: "消息4", content: "粒粒皆辛苦"}, ]) return ( <Fragment> <ul> { message.map((_item) => { return <li><Link to={`detail/${_item.id}/${_item.title}/${_item.content}`}> {_item.title} </Link></li> }) } </ul> <hr/> <Outlet/> </Fragment> ) }
和react-router-dom5版本一樣在路徑后面加
9.3.2接收Params參數
路由表需要接收Params參數
import About from "../pages/About"; import Home from "../pages/Home"; import Message from "../pages/Message"; import News from "../pages/News"; import Detail from "../pages/Detail"; import {Navigate} from "react-router-dom"; export const route = [ { path: "/about", element: <About/> }, { path: "/home", element: <Home/>, children: [ { path: "news", element: <News/> }, { path: "message", element: <Message/>, children: [ { path: "detail/:id/:title/:content", element: <Detail/> } ] } ] }, { path: "/", element: <Navigate to="/about"/> } ]
9.9.3 useParams
import React, {Fragment} from "react" import {useParams} from "react-router-dom" export default function Detail() { const {id, title, content} = useParams() return ( <Fragment> <ol> <li>{id}</li> <li>{title}</li> <li>{content}</li> </ol> </Fragment> ) }
9.9.4 useMatch
import React, {Fragment} from "react" import {useMatch} from "react-router-dom" export default function Detail() { const {id, title, content} = useMatch("/home/message/detail/:id/:title/:content").params return ( <Fragment> <ol> <li>{id}</li> <li>{title}</li> <li>{content}</li> </ol> </Fragment> ) }
注意useMatch這個hook要求把整個路徑全部當為參數傳遞進去
- 9.4 Search參數
9.4.1 傳遞Search參數
import React, {Fragment, useState} from "react" import {Link, Outlet} from "react-router-dom" export default function Message() { const [message] = useState([ {id: "001", title: "消息1", content: "鋤禾日當午"}, {id: "002", title: "消息2", content: "汗滴禾下土"}, {id: "003", title: "消息3", content: "誰知盤中餐"}, {id: "004", title: "消息4", content: "粒粒皆辛苦"}, ]) return ( <Fragment> <ul> { message.map((_item) => { return <li key={_item.id}><Link to={`detail?id=${_item.id}&title=${_item.title}&content=${_item.content}`}> {_item.title} </Link></li> }) } </ul> <hr/> <Outlet/> </Fragment> )
注意Search不需要接收
9.4.2 useSearchParams
import React, {Fragment} from "react" import {useSearchParams} from "react-router-dom" export default function Detail() { const [search, setSearch] = useSearchParams() const id = search.get("id") const title = search.get("title") const content = search.get("content") return ( <Fragment> <ol> <li>{id}</li> <li>{title}</li> <li>{content}</li> </ol> <button onClick={() => { setSearch('id=008&title=哈哈&content=嘻嘻') }}>點我更新Search </button> </Fragment> ) }
這個hook類似useState,生成兩個,我們需要調用get方法以及合適的字段,就能拿到相應的狀態(tài)
- 9.5 state參數
9.5.1 傳遞state參數
import React, {Fragment, useState} from "react" import {Link, Outlet} from "react-router-dom" export default function Message() { const [message] = useState([ {id: "001", title: "消息1", content: "鋤禾日當午"}, {id: "002", title: "消息2", content: "汗滴禾下土"}, {id: "003", title: "消息3", content: "誰知盤中餐"}, {id: "004", title: "消息4", content: "粒粒皆辛苦"}, ]) return ( <Fragment> <ul> { message.map((_item) => { return <li key={_item.id}><Link to="detail" state={{ id: _item.id, title: _item.title, content: _item.content }} >{_item.title} </Link></li> }) } </ul> <hr/> <Outlet/> </Fragment> ) }
9.5.2 useLocation
import React, {Fragment} from "react" import {useLocation} from "react-router-dom" export default function Detail() { const {state: {id, title, content}} = useLocation() return ( <Fragment> <ol> <li>{id}</li> <li>{title}</li> <li>{content}</li> </ol> </Fragment> ) }
我們需要連續(xù)解構賦值,在useLocation中將狀態(tài)state解構,再將想要的狀態(tài)從stae中結構
- 9.6 編程式路由導航
9.6.1 useNavigate
import React, {Fragment, useState} from "react" import {Link, Outlet, useNavigate} from "react-router-dom" export default function Message() { const navigate = useNavigate() function showDetail(item) { navigate("detail", { replace: false, state: { id: item.id, title: item.title, content: item.content } }) } const [message] = useState([ {id: "001", title: "消息1", content: "鋤禾日當午"}, {id: "002", title: "消息2", content: "汗滴禾下土"}, {id: "003", title: "消息3", content: "誰知盤中餐"}, {id: "004", title: "消息4", content: "粒粒皆辛苦"}, ]) return ( <Fragment> <ul> { message.map((_item) => { return <li key={_item.id}><Link to="detail" state={{ id: _item.id, title: _item.title, content: _item.content }} >{_item.title} </Link> <button onClick={() => { showDetail(_item) }}>查看詳情 </button> </li> }) } </ul> <hr/> <Outlet/> </Fragment> ) }
我們要用useNavigate構造一個實例就是navigate是一個函數,我們可以傳遞兩個參數,第一個是路徑,第二個是一個對象
9.6.2 前進和后退
import React, {Fragment} from "react"; import {useNavigate} from "react-router-dom" export default function Title() { const navigate = useNavigate() function back() { navigate(-1) } function forWord() { navigate(1) } return ( <Fragment> <h2 style={{marginLeft: "50px"}}>React Router Demo</h2> <button onClick={forWord}>前進-》</button> <button onClick={back}>《-后退</button> <hr/> </Fragment> ) }
我們可以調用navigate這個函數,參是是-1是后退,1是前進
9.6.3 注意:
如果我們要傳遞state可以放到navigate函數的第二個參數里,別的參數形式,我們要直接拼接到url里
10. useInRouterContext
該hook是判斷組件是否在路由的上下文中,在返回true,反之false
import React, {Fragment} from "react" import {useLocation, useInRouterContext} from "react-router-dom" export default function Detail() { const {state: {id, title, content}} = useLocation() console.log(useInRouterContext()) return ( <Fragment> <ol> <li>{id}</li> <li>{title}</li> <li>{content}</li> </ol> </Fragment> ) }
11. useNavigationType
該hook返回的是導航的類型為3種,POP為頁面刷新,還有PUSH,REPLACE
import React, {Fragment} from "react" import {useLocation, useNavigationType} from "react-router-dom" export default function Detail() { const {state: {id, title, content}} = useLocation() console.log(useNavigationType()) return ( <Fragment> <ol> <li>{id}</li> <li>{title}</li> <li>{content}</li> </ol> </Fragment> ) }
12. useOutlet
該hook是用來展現當前組件中嵌套的路由組件
import React, {Fragment, useState} from "react" import {Navigate,Outlet,NavLink,useOutlet} from "react-router-dom" export default function Home() { const [sum, setSum] = useState(1) console.log(useOutlet()) return ( <Fragment> <h3>Home</h3> {sum === 2 ? <Navigate to="/about"/> : <h4>當前sum為{sum}</h4>} <button onClick={() => setSum(sum + 1)}>點我加一</button> <NavLink to="message">message</NavLink> <NavLink to='news'>news</NavLink> <Outlet/> </Fragment> ) }
注意,若組件子路由組件沒掛載就返回NULL,反之返回路由對象
13.useResolvedPath
該hook是幫我們解析路徑的,可以分析出路徑,以及各種參數
import React, {Fragment} from "react" import {useLocation, useResolvedPath} from "react-router-dom" export default function Detail() { const {state: {id, title, content}} = useLocation() console.log(useResolvedPath()) return ( <Fragment> <ol> <li>{id}</li> <li>{title}</li> <li>{content}</li> </ol> </Fragment> ) }
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
react18中react-redux狀態(tài)管理的實現
本文主要介紹了react18中react-redux狀態(tài)管理的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-05-05React Native自定義Android的SSL證書鏈校驗
這篇文章主要為大家介紹了React Native自定義Android的SSL證書鏈校驗示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10react使用useState修改對象或者數組的值無法改變視圖的問題
這篇文章主要介紹了react使用useState修改對象或者數組的值無法改變視圖的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08