1概念
1.1?分类
前端路由:path-component
后端路由:path-function
1.2?路由原理
![](https://img-blog.csdnimg.cn/img_convert/6125788cad6e6d6231074bcbc7d950c5.png)
借助于BOM中的history,栈结构,默认为push。
push:压栈,出栈
repace:替换栈顶记录
2基本使用
2.1 v5.3.3
路由组件(Home):this.props={history/location/match}
一般组件(Header):this.props={ }
import { withRouter } from 'react-router-dom'
// 一般组件没有history属性等,用withRouter函数解决,返回值是一个新组件
export default withRouter(Header)
console.log(this.props.location.pathname)//地址栏路由
console.log(this.props.match.path)
console.log(this.props.match.url)
![e95ac8e4c2a848c05bcdde6213ac2bb0.png](https://img-blog.csdnimg.cn/img_convert/e95ac8e4c2a848c05bcdde6213ac2bb0.png)
index.js
BrowserRouter:使用H5的history;兼容性差一点;刷新后state参数还在;用的多
HashRouter:url#后的内容不会发给服务器,兼容性好一点;刷新后state参数不在;解决路径错误问题
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
// HashRouter带#
import { BrowserRouter } from 'react-router-dom';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
App.jsx
import { Route, Link, NavLink, Switch, Redirect } from 'react-router-dom'
export default class App extends Component {
render () {
return (
<div>
<div className="row">
<div className="col-xs-offset-2 col-xs-8">
<Header />
</div>
</div>
<div className="row">
{/* --------导航区-------- */}
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
{/* 1.原生html中,靠<a>跳转不同的页面 */}
{/* <a className="list-group-item" href="./about.html">About</a> */}
{/* 2.在React中靠路由链接实现切换组件--编写路由链接 */}
{/*a. 测试模糊匹配(默认) */}
<Link className="list-group-item" to="/about/a/b">About</Link>
{/*b. NavLink点击追加高亮类名 */}
{/* <NavLink activeClassName="demo" className="list-group-item" to="/home">Home</NavLink> */}
{/*c.封装NavLink,标签体内容Home为children属性;默认为push */}
<MyLink to="/home">Home</MyLink>
{/*d.问题:to改为二级路由后刷新:找不到bootstrap文件 ;改为绝对路径:public(React)或者/(常用)*/}
<MyLink to="/test/demo">测试样式丢失</MyLink>
</div>
</div>
{/* --------展示区-------- */}
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
{/* 注册路由:<Switch>组件匹配成功后,不再匹配其他组件。包裹路由组件,提高路由匹配效率 */}
<Switch>
{/* exact开启精准匹配,需要再开启。 */}
<Route path="/about" component={About} exact />
<Route path="/home" component={Home} />
<Route path="/home" component={Test} />
<Route path="/test/demo" component={Test} />
{/* 匹配不到显示,放到最下面 */}
<Redirect to="/about" />
</Switch>
</div>
</div>
</div>
</div>
</div>
)
}
}
2.2 v6.3.0
App.jsx
import { NavLink, Routes, Route, Navigate, useRoutes } from 'react-router-dom'
import routes from './routes'
export default function App () {
function computedClassName ({ isActive }) {
return isActive ? 'list-group-item atguigu' : 'list-group-item'
}
//根据路由表生成对应的路由规则
const element = useRoutes(routes)
return (
<div>
<div className="row">
<Header />
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
{/* 路由链接:className={()=>{}}函数值可以全局定义实现复用*/}
<NavLink className={computedClassName} to="/about">About</NavLink>
{/* navLInk的end属性会去掉父级高亮 */}
<NavLink className={computedClassName} to="/home" end>Home</NavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
{/* 1.注册路由:Routes包裹Route:path-element ;caseSensitive是否区分大小写 */}
{/* <Routes>
<Route path="/About" caseSensitive={false} element={<About />} />
<Route path="/home" element={<Home />} />
{/* navigate渲染引起视图切换,包含replace属性 */}
<Route path="/" element={<Navigate to="/about" />} />
</Routes> */}
{/* 2.路由表 */}
{element}
</div>
</div>
</div>
</div>
</div>
)
}
routes/index.js
import { Navigate } from 'react-router-dom'
const arr=[
{
path: '/about',
element:<About/>
},
{
path: '/home',
element: <Home />,
children: [//二级路由
{
path: 'news',
element:<News/>
},
{
path: 'message',
element: <Message />,
children: [
//params参数
// {
// path: 'detail/:id/:title/:content',
// element:<Detail/>
// },
//search参数
// {
// path: 'detail',
// element:<Detail/>
// },
//state参数
{
path: 'detail',
element:<Detail/>
},
]
}
]
},
{
path: '/',
element:<Navigate to="/about"/>
},
]
export default arr;
3 嵌套路由
![](https://img-blog.csdnimg.cn/img_convert/d67c8ba55d7a86deefb81bed48fa536f.png)
3.1 v5.3.3
<div>
<h3>我是Home的内容</h3>
{/* 二级路由页面 */}
<div>
<ul className="nav nav-tabs">
<li>
{/* home组件匹配到了; /home/news组件匹配到了 。 */}
<MyNavLink to="/home/news">News</MyNavLink>
</li>
<li>
<MyNavLink to="/home/message">Message</MyNavLink>
</li>
</ul>
<Switch>
<Route path="/home/news" component={News} />
<Route path="/home/message" component={Message} />
<Redirect to="/home/news" />
</Switch>
</div>
</div>
3.2 v6.3.0
import { Outlet, NavLink } from 'react-router-dom'
<div>
<ul className="nav nav-tabs">
<li>
<NavLink className="list-group-item" to="news" >News</NavLink>
</li>
<li>
<NavLink className="list-group-item" to="message">Message</NavLink>
</li>
</ul>
{/* 指定路由组件呈现的位置 */}
<Outlet />
</div>
4 路由传参
刷新后参数不丢,清缓存丢。
携带参数方式:query;params;body(json/urlencoded)
![03daaa22c9f219c0abf68e926ab04131.png](https://img-blog.csdnimg.cn/img_convert/03daaa22c9f219c0abf68e926ab04131.png)
4.1 v5.3.3
4.1.1 params参数
//路由链接
<Link to={`/home/message/detail/${item.id}/${item.title}`}>{item.title}</Link>
//注册路由
<Route path="/home/message/detail/:id/:title" component={Detail} />
//接收
const { id, title } = this.props.match.params
4.1.2 search参数
import qs from 'querystring'
<Link to={`/home/message/detail/?id=${item.id}&title=${item.title}`}>{item.title}</Link>
<Route path="/home/message/detail" component={Detail} />
//接收
const { search } = this.props.location
console.log(search, 'search参数')//?id=1&title=消息1
const { id, title } = qs.parse(search.slice(1))
//扩展
let obj = { name: 'tom', age: 18 }
console.log(qs.stringify(obj))//name=tom&age=18
let str = 'name=ming&age=19'
console.log(qs.parse(str))//{name: 'ming', age: '19'}
4.1.3 state参数
<Link to={{ pathname: '/home/message/detail', state: { id: item.id, title: item.title } }}>{item.title}</Link>
<Route path="/home/message/detail" component={Detail} />
//接收
const { id, title } = this.props.location.state || {}
4.2 v6.3.0
4.2.1 params参数
import { useParams, useMatch } from 'react-router-dom'
<Link to={`detail/${item.id}/${item.title}/${item.content}`}>{item.title}</Link>
// 方式一:
const { id, title, content } = useParams()
// 方式二:
const x = useMatch('/home/message/detail/:id/:title/:content')
console.log(x.params);//{id: '2', title: '消息2', content: '2222内容'}
4.2.2 search参数
import { useSearchParams, useLocation} from 'react-router-dom'
<Link to={`detail?id=${item.id}&title=${item.title}&content=${item.content}`}>{item.title}</Link>
// 方式一:
const [search, setSearch] = useSearchParams();
const id = search.get('id');
const title = search.get('title');
const content = search.get('content');
{/* <button onClick={() => { setSearch('id=0&title=haha&content=xixi') }}>更新search参数</button> */}
// 方式二:
const x = useLocation()
console.log(x.search)//?id=1&title=%E6%B6%88%E6%81%AF1&content=1111%E5%86%85%E5%AE%B9
4.2.3 state参数
import { useLocation } from 'react-router-dom'
<Link to="detail" state={{ id: item.id, title: item.title, content: item.content }}>{item.title}</Link>
// 方式一:
const { state: { id, title, content } } = useLocation()
5 编程式导航
![](https://img-blog.csdnimg.cn/img_convert/f0195057b62315482c5196f0ad16c682.png)
5.1 v5.3.3
//push跳转+携带params参数
this.props.history.push(`/home/message/detail/${id}/${title}`)
//push跳转+携带search参数
this.props.history.push(`/home/message/detail?id=${id}&title=${title}`)
//push跳转+携带state参数
this.props.history.push(`/home/message/detail/`, { id, title })
this.props.history.replace(`/home/message/detail/`, { id, title })
this.props.history.goBack()
this.props.history.goForward()
this.props.history.go(-1)
5.2 v6.3.0
import { useNavigate } from 'react-router-dom'
const navigate = useNavigate()
navigate(`detail/${item.id}/${item.title}/${item.content}`, {
replace: false,
})
navigate(`detail?id=${item.id}&title=${item.title}&content=${item.content}`, {
replace: false,
})
navigate('detail', {
replace: false,
state: {
id: item.id, title: item.title, content: item.content
}
})
navigate(-1)
navigate(1)
6 其他钩子
import { useNavigationType, useResolvedPath,useInRouterContext,useOutlet } from 'react-router-dom'
// push/replace/pop(怎么来的当前页面?刷新!)
console.log(useNavigationType())
// 给定一个 URL值,解析其中的:path、search、hash值。
console.log(useResolvedPath('/user?id=001&name=tom#qwe'))//{pathname: '/user', search: '?id=001&name=tom', hash: '#qwe'}
//被BrowserRouter包裹返回true
const navigate = useInRouterContext()
console.log(navigate)
// 返回什么???
console.log(useOutlet(), 'useOutlet')
|