使用路由前,首先要进行安装
yarn add react-router-dom 或者 npm i react-router-dom
直接安装的话,默认安装的是6版本的,所有下面介绍的也是6版本的
目录
路由模式
- 常用的有3种,浏览器模式BrowserRouter,hash模式HashRouter,历史模式HishtoryRouter
- 浏览器模式BrowserRouter会使我们地址栏的路由看着更像是一个正常的路由
- 而hash模式的路由会多出一个#号
实现一个简单路由
1. 首先在index.js文件中做出配置 React的index.js页面相当于Vue的main.js,入口
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
// 1. 引入BrowserRouter,并重命名为Router,想要什么路由模式,就引入对应的路由模式
import { BrowserRouter as Router } from 'react-router-dom'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
{/* 2. 使用Router进行包裹,这样在App页面的所有地方都可以直接使用路由了 */}
<Router>
<App />
</Router>
</React.StrictMode>
);
reportWebVitals();
2. 在App.js文件中进行各种路由配置
App.js
import React from 'react'
import { Routes, Route, Link } from 'react-router-dom'
import Home from './pages/Home.jsx'
import About from './pages/About.jsx'
export default function App() {
return (
<div>
<h2>App</h2>
<hr />
<Link to="/">点击跳转Home</Link> | <Link to="/about">点击跳转About</Link>
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
</Routes>
</div>
)
}
- Routes是5版本的Switch升级而来,Routes只能包裹Route
- 被Routes包裹的Route,只会匹配第一个符合要求的路由(类似于Switch...case,多选一)
路由是/about时,只会匹配About组件,而不会匹配Home
- Route指定路由规则,path指定路径,而element指定要渲染的组件
- Link类似于Vue的router-link,可以显示的声明跳转,里面的to属性就是跳转的路由
嵌套路由
- 路由里面嵌套路由,也就是Route里面嵌套Route,在谁的里面嵌套,就是谁的子路由
- 需要在父级路由里面声明路由出口(Outlet),不然子路由对应的组件渲染那去呢
App.js
import React from 'react'
import { Routes, Route, Link } from 'react-router-dom'
import Home from './pages/Home.jsx'
import About from './pages/About.jsx'
import Music from './pages/Music.jsx'
import Movie from './pages/Movie.jsx'
export default function App() {
return (
<div>
<h2>App</h2>
<hr />
<Link to="/">点击跳转Home</Link> | <Link to="/about">点击跳转About</Link>
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/about" element={<About />}>
<Route index element={<Music />}></Route>
<Route path="music" element={<Music />}></Route>
<Route path="movie" element={<Movie />}></Route>
</Route>
</Routes>
</div>
)
}
- Route的index属性,类似于Vue 的重定向,直接指定路由进去后默认渲染的子路由
About.jsx (子级路由Music和Movie的父级路由)
import React from 'react'
import { Outlet, Link } from 'react-router-dom'
export default function About() {
return (
<div>
<h2>About</h2>
<p>下面是子级路由</p>
<Link to="music">跳转Music</Link> | <Link to="movie">跳转Movie</Link>
<Outlet></Outlet>
</div>
)
}
- 在父级路由里面,子级路由可以直接写,不用带/和父级路由,它会根据父路由自动拼接
动态路由
- 在对应的路由后面,无论添加什么,都会匹配同一个组件
import React from 'react'
import { Routes, Route, Link } from 'react-router-dom'
import Home from './pages/Home.jsx'
import About from './pages/About.jsx'
import Music from './pages/Music.jsx'
import Movie from './pages/Movie.jsx'
import My from './pages/My.jsx'
export default function App() {
return (
<div>
<h2>App</h2>
<hr />
<Link to="/">点击跳转Home</Link> | <Link to="/about">点击跳转About</Link>{' '}
<Routes>
{/* 普通路由 */}
<Route path="/" element={<Home />}></Route>
{/* 嵌套路由 */}
<Route path="/about" element={<About />}>
<Route index element={<Music />}></Route>
<Route path="music" element={<Music />}></Route>
<Route path="movie" element={<Movie />}></Route>
</Route>
{/* 动态路由 */}
<Route path="/my/:id" element={<My />}></Route>
</Routes>
</div>
)
}
获取动态路由参数
- useParams() 返回的是一个动态路由参数的对象
My.jsx
import React from 'react'
import { useParams } from 'react-router-dom'
export default function My() {
// let { id } = useParams()
// console.log(id)
let params = useParams()
console.log(params)
return (
<div>
<h2>My</h2>
<p>获取到的动态路由参数为:{params.id}</p>
</div>
)
}
获取路径(查询)参数
- 类似于这种: to = "/friend?name=张三" 获取问号后面的
使用 useLocation()
App.js
import React from 'react'
import { Routes, Route, Link } from 'react-router-dom'
import Home from './pages/Home.jsx'
import About from './pages/About.jsx'
import Music from './pages/Music.jsx'
import Movie from './pages/Movie.jsx'
import My from './pages/My.jsx'
import Friend from './pages/Friend.jsx'
export default function App() {
return (
<div>
<h2>App</h2>
<hr />
<Link to="/">点击跳转Home</Link> | <Link to="/about">点击跳转About</Link>{' '}
| <Link to="/friend?name=zs">点击跳转Friend</Link>
<Routes>
{/* 普通路由 */}
<Route path="/" element={<Home />}></Route>
{/* 嵌套路由 */}
<Route path="/about" element={<About />}>
<Route index element={<Music />}></Route>
<Route path="music" element={<Music />}></Route>
<Route path="movie" element={<Movie />}></Route>
</Route>
{/* 动态路由 */}
<Route path="/my/:id" element={<My />}></Route>
{/* 查询参数 */}
<Route path="/friend" element={<Friend />}></Route>
</Routes>
</div>
)
}
Friend.jsx
import React from 'react'
import { useLocation } from 'react-router-dom'
export default function Friend() {
let location = useLocation()
console.log(location)
return (
<div>
<h2>Friend</h2>
<p>获取到的查询参数为:{location.search.slice(1).split('=')[1]}</p>
</div>
)
}
使用useSearchParams() 这个相比useLocation(),可以直接获取查询参数的值
- 底层使用了URLSearchParams()对象,里面包含了很多查询参数的方法
- 返回的是一对值,用数组进行接收
App.js
import React from 'react'
import { Routes, Route, Link } from 'react-router-dom'
import Home from './pages/Home.jsx'
import About from './pages/About.jsx'
import Music from './pages/Music.jsx'
import Movie from './pages/Movie.jsx'
import My from './pages/My.jsx'
import Friend from './pages/Friend.jsx'
export default function App() {
return (
<div>
<h2>App</h2>
<hr />
<Link to="/">点击跳转Home</Link> | <Link to="/about">点击跳转About</Link>{' '}
| <Link to="/friend?name=zs">点击跳转Friend</Link>
<Routes>
{/* 普通路由 */}
<Route path="/" element={<Home />}></Route>
{/* 嵌套路由 */}
<Route path="/about" element={<About />}>
<Route index element={<Music />}></Route>
<Route path="music" element={<Music />}></Route>
<Route path="movie" element={<Movie />}></Route>
</Route>
{/* 动态路由 */}
<Route path="/my/:id" element={<My />}></Route>
{/* 查询参数 */}
<Route path="/friend" element={<Friend />}></Route>
</Routes>
</div>
)
}
Friend.jsx
import React from 'react'
import { useLocation, useSearchParams } from 'react-router-dom'
export default function Friend() {
// useLocation()
let location = useLocation()
console.log('useLocation()', location)
// useSearchParams()
let [search, serSearch] = useSearchParams()
console.log('useSearchParams()', search)
// 修改查询参数,执行的是覆盖操作,如果有多个查询参数,则需要补全
const changeName = () => {
serSearch({
name: 'ls',
})
}
return (
<div>
<h2>Friend</h2>
<p>获取到的查询参数为:{location.search.slice(1).split('=')[1]}</p>
<p>获取到的查询参数为:{search.get('name')}</p>
<button onClick={changeName}>修改传过来查询参数:name</button>
</div>
)
}
编程式导航
useNavigate(to[,options]) 5使用的是useHistory()
- to是跳往的路由地址,options可选,路由配置项,可以传递一些参数什么的
Home.jsx
import React from 'react'
import { useNavigate } from 'react-router-dom'
export default function Home() {
const navigate = useNavigate()
const toAbout = () => {
navigate('/about?age=24', {
state: {
name: 'zs',
},
// 则不可回退
replace: true,
})
}
return (
<div>
<h2>Home</h2>
<button onClick={toAbout}>跳往About</button>
</div>
)
}
About.jsx
import React from 'react'
import { useLocation } from 'react-router-dom'
export default function About() {
const params = useLocation()
console.log(params)
return (
<div>
<h2>About</h2>
</div>
)
}
NavLink与Link与Navigate
Link
- 可以直接指定要跳转的路由 to属性指定路由,最终会转换为a元素
<Link to="music">跳转Music</Link> | <Link to="movie">跳转Movie</Link>
NavLink
- 可以直接指定要跳转的路由,选中的时候,会比Link多一个active的类名。我们可以通过这个类名来指定一些选中时的样式,最终会转换为a元素
- to属性指定路由
- style属性指定样式,是个函数形式,函数的第一个参数是个对象,里面有个isActive表是否选中,是一个布尔值
未选中
选中
- 我们也可以直接指定一个calssName
import React from 'react'
import { NavLink } from 'react-router-dom'
export default function About() {
let borderStyle = {
border: '1px solid pink',
color: 'red',
}
return (
<div>
<h2>About</h2>
<NavLink
to="music"
style={({ isActive }) => {
console.log(isActive)
if (isActive) {
return borderStyle
}
}}
>
跳转Music
</NavLink>
<NavLink to="movie">跳转Movie</NavLink>
</div>
)
}
Navigate
- to属性指定跳转的路由,replace表是否替换(不保留历史记录)
- 一般做动态路由用,或者做权限
import React, { useState } from 'react'
import { useNavigate, Navigate } from 'react-router-dom'
export default function Home() {
let [flag, setFlag] = useState(false)
const toabout = () => {
setFlag((flag = !flag))
}
return (
<div>
<h2>Home</h2>
<button onClick={toabout}>点击跳转About</button>
{flag && <Navigate to="/about">跳往About</Navigate>}
</div>
)
}
useRoutes
- 用法类似于vue的路由
单独创建一个router.js文件,存放路由配置规则
router.js
import Home from '../pages/Home.jsx'
import About from '../pages/About.jsx'
import Login from '../pages/Login.jsx'
import NotFound from '../pages/NotFound.jsx'
import Music from '../pages/Music.jsx'
import Movie from '../pages/Movie.jsx'
const routes = [
{
path: '/',
element: <Home />,
meta: {
title: '首页',
hide: false,
},
},
{
path: '/about',
element: <About />,
meta: {
title: '关于',
hide: false,
},
children: [
{
path: 'music',
element: <Music />,
meta: {
title: '音乐',
hide: false,
},
},
{
path: 'movie',
element: <Movie />,
meta: {
title: '电影',
hide: false,
},
},
],
},
{
path: '/login',
element: <Login />,
meta: {
hide: true,
},
},
{
path: '*',
element: <NotFound />,
meta: {
hide: true,
},
},
]
export default routes
App.js
import React from 'react'
import routes from './routes/routes'
import { useRoutes, NavLink } from 'react-router-dom'
export default function App() {
const element = useRoutes(routes)
console.log(routes)
return (
<div>
<h2>App</h2>
{/* 显示声明 */}
<ul>
{routes.map(
(item) =>
!item.meta.hide && (
<li key={item.path}>
<NavLink to={item.path}>{item.meta.title}</NavLink>
{item.children && (
<ul>
{item.children.map((items) => (
<li key={items.path}>
<NavLink to={item.path + '/' + items.path}>
{items.meta.title}
</NavLink>
</li>
))}
</ul>
)}
</li>
)
)}
</ul>
{/* 路由配置 */}
{element}
</div>
)
}
原文链接:https://blog.csdn.net/qq_52845451/article/details/127149936
此处评论已关闭