1.版本区分
react-router有两个版本,一个叫react-router,另一个叫react-router-dom。下面讲一下这两个路由的区别:
react-router:
- 这是react-router的核心包,同样能提供路由功能。
- 平台无关 的,意味着可以用于 Web、React Native、Node.js 等不同平台。
- 如果你要做的是 Web 应用以外的项目(例如 React Native 或其他环境),就应该使用这个包。
react-router-dom:
- 这是
react-router的 Web 特定实现,它依赖于浏览器的 DOM API,专门为 Web 应用提供路由支持。 - 如果你是做 Web 项目,那么应该使用
react-router-dom,它包括了react-router的核心功能,并提供了 DOM 特定的功能(如<BrowserRouter>、<Link>等)。 react-router-dom是最常用于 Web 项目的选择。
2.安装react-router-dom
# NPM
npm install react-router-dom
# PNPM
pnpm add react-router-dom
3.createBrowserRouter
这是React Router v6 的一个新特性。跟vue-router很相似,换句话说就是用数组包对象的方式配置路由规则。
4.路由配置
首先,跟vue项目一样在src目录下创建router/index.jsx文件结构。
下面是:index.jsx
import { createBrowserRouter } from 'react-router-dom'
import Home from '../Home'
import About from '../About'
// 创建路由实例
const router = createBrowserRouter([
{
path: '/home',
element: <Home />
},
{
path: '/about',
element: <About />
}
])
// 导出路由实例
export default router
在main.jsx中进行注册:
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
// RouterProvider用来注册路由
import { RouterProvider } from 'react-router-dom'
// 导入刚才导出的路由实例
import router from './router'
createRoot(document.getElementById('root')).render(
<StrictMode>
{/* 进行注册 */}
<RouterProvider router={router}></RouterProvider>
</StrictMode>
)
然后就可以导航了:
5.路由导航(跳转)
有两种导航方式:
- 声明式导航
- 编程式导航
声明式导航
这个几乎跟vue一模一样,Link相当于vue中的router-link。
import { Link } from 'react-router-dom'
export default function Home() {
return (
<div className='home'>
<h1>这是Home页</h1>
{/* 声明式导航 */ }
<Link to='/about'>跳转到About页</Link>
</div>
)
}
编程式导航
这个也很简单,跟vue中的router.push很相似。
需要从react-router-dom中导入useNavigate Hook。
import { useNavigate } from 'react-router-dom'
export default function About() {
const navigate = useNavigate()
return (
<div className='about'>
<h1>这是About页</h1>
{/* 编程式导航 */ }
<button onClick={ () => navigate('/home') }>跳转到Home页</button>
</div>
)
}
6.路由传参
路由传参分为两种:
searchParams传参params传参
searchParams传参
下面Home.jsx传递参数:
import { useNavigate } from 'react-router-dom'
export default function Home() {
const navigate = useNavigate()
return (
<div className='home'>
<h1>这是Home页</h1>
{/* 声明式导航 */ }
<button onClick={()=>navigate('/about?id=007&name=akbar')}>跳转到About页</button>
</div>
)
}
也可以使用声明式导航传参:
下面用About.jsx接受参数:
接受参数的时候需要从需要从react-router-dom中导入useSearchParams Hook。
import { useSearchParams } from 'react-router-dom'
export default function About() {
const [params] = useSearchParams()
const id = params.get('id')
const name = params.get('name')
return (
<div className='about'>
<h1>这是About页</h1>
<p>id: { id }</p>
<p>name: { name }</p>
</div>
)
}
小知识点
const [params] = useSearchParams(),这里的params代表原生的web apiURLSearchParams对象。
URLSearchParams对象提供了一个get方法,用于获取特定的查询参数值。这个方法接受一个查询参数的名称作为参数,并返回该参数的值。
效果图:
params传参
params传参是用article/:id这种方式传递数据,比如这里的id。
下面是ArticleList.jsx:
import { useNavigate } from 'react-router-dom'
export default function ArticleList() {
const navigate = useNavigate()
return (
<div className='article-list'>
<h1>文章列表</h1>
{/* 通过params的方式传递文章id */}
<button onClick={ () => navigate('/articlePreview/453')}>传递文章id453</button>
</div>
)
}
同样也可以使用声明式传参的方式传递参数
下面是ArticlePreview.jsx:
这里需要用到useNavigate Hook.
import { useParams } from 'react-router-dom'
export default function ArticlePreview() {
const params = useParams()
const articleId = params.id
return (
<div className='article-preview'>
<h1>文章预览</h1>
<p>接收到的文章id { articleId }</p>
</div>
)
}
然后在路由配置文件index.jsx进行配置:
import { createBrowserRouter } from 'react-router-dom'
import ArticlePreview from '../ArticlePreview'
import ArticleList from '../ArticleList'
const router = createBrowserRouter([
{
// 这里的:id就是要接受到的参数
path: '/articlePreview/:id',
element: <ArticlePreview />
},
{
path: 'articleList',
element: <ArticleList />
}
])
export default router
效果图:
7.嵌套路由
嵌套路由也跟vue-router非常相似,嵌套路由的路由出口时<Outlet />。
下面模拟一个管理系统页面,演示路由嵌套:
还有
Sidebar.jsx,这个我暂时不知道放到哪个文件夹,vue项目的话可以放到component目录下。
1.Layout.jsx:
import { Outlet } from 'react-router-dom'
import Sidebar from '../Sidebar'
export default function Layout() {
return (
<div className='layout'>
<Sidebar />
<main className='main'>
{/* Outlet是路由出口,相当于vue中的router-view */ }
<Outlet />
</main>
</div>
)
}
2.Sidebar.jsx:
import { NavLink } from 'react-router-dom'
export default function Sidebar() {
return (
<aside className='sidebar'>
<ul>
<NavLink
to='/'
className={ ({ isActive }) => isActive ? 'active' : '' }
>
<li>Home</li>
</NavLink>
<NavLink
to='/about' className={ ({ isActive }) => isActive ? 'active' : '' }
>
<li>About</li>
</NavLink>
</ul>
</aside>
)
}
为了实现路由高亮,我这里使用了<NavLink>,下面讲一下<NavLink>和<Link>的区别:
NavLink和Link都是react-router-dom提供的组件,用于在 React 应用中实现页面之间的导航。它们的作用非常相似,但也有一些关键的区别,适用于不同的场景。
Link组件:
Link是用于创建页面间导航的基本组件。当你需要在页面内跳转到另一个路由时(没有路由高亮需求时),可以使用Link来替代传统的 HTML<a>标签。
NavLink组件:
NavLink是Link的增强版,主要用于处理路由的激活状态。当一个链接指向的路由匹配当前 URL 时,NavLink会自动为这个链接添加一个active类(或者自定义的类名),通常用于高亮当前活动的链接。
NavLink的className属性可以接受一个函数,该函数接收一个 对象类型的参数,这个对象中我们可以解构出isActive参数,isActive是一个布尔值,表示该链接是否是当前激活状态。
然后再路由配置文件index.jsx中进行配置:
import { createBrowserRouter } from 'react-router-dom'
import Home from '../page/Home'
import About from '../page/About'
import Layout from '../layout/Layout'
const router = createBrowserRouter([
{
path: '/',
element: <Layout />,
children: [
{
// 这里不需要给Home组件指定路径,直接写index就可以,然后Home组件的路径就变成'/'
// index:true 跟vue-router中的redirect很相似
index: true,
element: <Home />
},
{
path: '/about',
element: <About />
}
]
},
])
export default router
8.404路由配置
首先写一个NotFound.jsx:
export default function NotFound() {
return (
<div className="not-found-container">
<h1 className="not-found-heading">404 - Page Not Found</h1>
<p className="not-found-description">Sorry, the page you are looking for doesn't exist.</p>
</div>
)
}
然后在路由配置文件index.jsx进行配置:
import { createBrowserRouter } from 'react-router-dom'
import Home from '../page/Home'
import About from '../page/About'
import Layout from '../layout/Layout'
import NotFound from '../page/NotFound'
const router = createBrowserRouter([
{
path: '/',
element: <Layout />,
children: [
{
index: true,
element: <Home />
},
{
path: '/about',
element: <About />
}
]
},
{
// *是通配符,当什么都不匹配的时候跳转到该路由
path: '*',
element: <NotFound/>
}
])
export default router
效果图:
9.两种路由模式
跟vue-router一样,react-router也有两种路由模式:
createBrowserRouter:history模式createHashRouter:hash模式