React-RouterV6
https://reactrouter.com/en/main/components/routes
简介
-
react-router :核心模块‘ react路由的大部分的核心功能,包括路由匹配算法和大部分的核心组件和钩子
-
react-router-dom React组件中用于路由的软件包,包括react-router的所有内容,还添加了一些特定的Dom的api
-
react-router-native 开发reactNavite应用,包括react-router的所有内容,添加了一些react-native的api
react-routerV6版本和V5版本的区别
- 包大小的不同 V5 大小在20.8k左右,压缩后在7.3k左右;V6 大小在10.8k左右,压缩后在3.8k左右
- Route 特性变更
- path 当前页面对应的URL地址
- element 路由匹配时,渲染哪个组件 ;替代了V5里的component和render
- Routes替代了Switch
- 嵌套路由更简单
- useNavigate替代了useHistory
- 移除了activeClassName
- 钩子useRoutes替代了react-router-config
路由使用
-
路由表配置
src/router/index.js
import React from 'react' import { Routes, Route } from 'react-router-dom' import Home from '../Home' import Course from '../Course' export default function MRoute() { return ( // Routes替代了Switch <Routes> {/* element替代了component */} <Route path="/home" element={<Home />}></Route> <Route path="/course" element={<Course />}></Route> </Routes> ) }
-
路由视图
App.js
import React from 'react' import { BrowserRouter as Router } from 'react-router-dom' // 引入路由表 import MRoute from './router' export default function App() { return ( <Router> <MRoute /> </Router> ) }
路由重定向
React-routerV6版本中已经没有了Redirect组件
-
第一种:使用Navigate组件替代
src/router/index.js
import React from 'react' import { Routes, Route, Navigate } from 'react-router-dom' import Home from '../Home' import Course from '../Course' export default function MRoute() { return ( // Routes替代了Switch <Routes> {/* element替代了component */} <Route path="/home" element={<Home />}></Route> <Route path="/course" element={<Course />}></Route> {/* 路由重定向 */} <Route path="/" element={<Navigate to="/home" />}></Route> </Routes> ) }
-
第二种:自定义Redirect组件
import { useEffect } from 'react' import { useNavigate } from 'react-router-dom' export default function Redirect(props) { const navigate = useNavigate() useEffect(() => { // replace: true 代表的是要替换掉之前的页面 navigate(props.to, { replace: true }) }) return null }
<Routes> {/* element替代了component */} <Route path="/home" element={<Home />}></Route> <Route path="/course" element={<Course />}></Route> {/* 路由重定向 */} <Route path="/" element={<Redirect to="/home" />}></Route> </Routes>
-
404页面
<Routes> {/* element替代了component */} <Route path="/home" element={<Home />}></Route> <Route path="/course" element={<Course />}></Route> {/* 路由重定向 */} <Route path="/" element={<Redirect to="/home" />}></Route> {/* 404页面 */} <Route path="*" element={<NotFound />}></Route> </Routes>
声明式导航和编程式导航
-
声明式导航
<Router> <NavLink to="/home">首页</NavLink> <NavLink to="/course">课程</NavLink> <hr /> <MRoute /> </Router>
NavLink组件会自动给当前的匹配到的路由NavLink添加一个class名为active,要实现高亮效果设置active样式
自定义class名
<Router>
<NavLink
to="/home"
className={({ isActive }) => (isActive ? 'my-active' : '')}
>
首页
</NavLink>
<NavLink
to="/course"
className={({ isActive }) => (isActive ? 'my-active' : '')}
>
课程
</NavLink>
<hr />
<MRoute />
</Router>
NavLink有一个属性className,它接收一个函数,该函数的参数是一个对象,里面有一个属性isActive,
我们可以根据这个属性的值是否为true来判断是否添加class名
-
编程式导航
import React from 'react' import { useNavigate } from 'react-router-dom' export default function Home() { // 使用useNavigate这个钩子 可以通过js的方式实现跳转 const navigate = useNavigate() return ( <div> <div>Home</div> <button onClick={() => navigate('/course')}>去课程</button> </div> ) }
嵌套路由
-
基本配置
import React from 'react' import { Routes, Route, Navigate } from 'react-router-dom' import Home from '../Home' import Course from '../Course' import Redirect from '../Redirect' import NotFound from '../NotFound' import JsCourse from '../JsCourse' import VueCourse from '../VueCourse' import ReactCourse from '../ReactCourse' export default function MRoute() { return ( // Routes替代了Switch <Routes> {/* element替代了component */} <Route path="/home" element={<Home />}></Route> <Route path="/course" element={<Course />}> {/* 嵌套路由 */} {/* index匹配到的父路径 */} <Route index element={<Redirect to="/course/js" />}></Route> <Route path="js" element={<JsCourse />}></Route> <Route path="vue" element={<VueCourse />}></Route> <Route path="react" element={<ReactCourse />}></Route> </Route> {/* 路由重定向 */} <Route path="/" element={<Redirect to="/home" />}></Route> {/* 404页面 */} <Route path="*" element={<NotFound />}></Route> </Routes> ) }
-
通过Outlet组件实现嵌套路由的视图显示
import React from 'react' import { NavLink, Outlet } from 'react-router-dom' export default function Course() { return ( <div> <NavLink to="/course/js">js课程</NavLink> <NavLink to="/course/vue">vue课程</NavLink> <NavLink to="/course/react">react课程</NavLink> <hr /> <Outlet /> </div> ) }
动态路由
-
query形式传参
export default function Home() { // 使用useNavigate这个钩子 可以通过js的方式实现跳转 const navigate = useNavigate() return ( <div> <div>Home</div> <button onClick={() => navigate('/course')}>去课程</button> {/* 新闻 */} <NavLink to="/news?id=1">军事新闻</NavLink> <NavLink to="/news?id=2">体育e新闻</NavLink> <NavLink to="/news?id=3">娱乐新闻</NavLink> </div> ) }
//路由配置
<Routes>
{/* element替代了component */}
<Route path="/home" element={<Home />}></Route>
<Route path="/course" element={<Course />}>
{/* 嵌套路由 */}
{/* index匹配到的父路径 */}
<Route index element={<Redirect to="/course/js" />}></Route>
<Route path="js" element={<JsCourse />}></Route>
<Route path="vue" element={<VueCourse />}></Route>
<Route path="react" element={<ReactCourse />}></Route>
</Route>
{/* 新闻 */}
<Route path="/news" element={<News />}></Route>
{/* 路由重定向 */}
<Route path="/" element={<Redirect to="/home" />}></Route>
{/* 404页面 */}
<Route path="*" element={<NotFound />}></Route>
</Routes>
//News.js 获取参数
import React from 'react'
import { useSearchParams } from 'react-router-dom'
export default function News() {
// 通过useSearchParams钩子函数来获取query形式的参数
const [searchparams, setSearchParams] = useSearchParams()
return <div>News{searchparams.get('id')}</div>
}
/*
searchparams.get('id') 获取路由参数的值
searchparams.has('id') 判断参数是否存在
setSearchParams({'id':45}) 在当前页面修改路由参数的值
*/
- params形式传参
import React from 'react'
import { useParams } from 'react-router-dom'
export default function NewsDetail() {
// 通过useParams 接收params传递的参数
const params = useParams()
return <div>NewsDetail{params.id}</div>
}
<Routes>
{/* element替代了component */}
<Route path="/home" element={<Home />}></Route>
<Route path="/course" element={<Course />}>
{/* 嵌套路由 */}
{/* index匹配到的父路径 */}
<Route index element={<Redirect to="/course/js" />}></Route>
<Route path="js" element={<JsCourse />}></Route>
<Route path="vue" element={<VueCourse />}></Route>
<Route path="react" element={<ReactCourse />}></Route>
</Route>
{/* 新闻 */}
<Route path="/news" element={<News />}></Route>
{/* params形式 */}
<Route path="/newsdetail/:id" element={<NewsDetail></NewsDetail>}></Route>
{/* 路由重定向 */}
<Route path="/" element={<Redirect to="/home" />}></Route>
{/* 404页面 */}
<Route path="*" element={<NotFound />}></Route>
</Routes>
{/* params形式传参 */}
<NavLink to="/newsdetail/1">军事新闻</NavLink>
<NavLink to="/newsdetail/2">体育e新闻</NavLink>
<NavLink to="/newsdetail/3">娱乐新闻</NavLink>
路由拦截
-
路由拦截组件封装
//AuthComponent.js import React from 'react' import Redirect from './Redirect' export default function AuthComponent(props) { // 获取当前组件 const Comp = props.children.type return localStorage.getItem('token') ? <Comp /> : <Redirect to="/login" /> }
-
配置登录拦截
<Routes> {/* element替代了component */} <Route path="/home" element={ <AuthComponent> <Home /> </AuthComponent> } ></Route> <Route path="/login" element={<Login />}></Route> {/* params形式 */} <Route path="/newsdetail/:id" element={<NewsDetail></NewsDetail>}></Route> {/* 路由重定向 */} <Route path="/" element={<Redirect to="/home" />}></Route> {/* 404页面 */} <Route path="*" element={<NotFound />}></Route> </Routes>
-
登录功能
import React from 'react' import { useNavigate } from 'react-router-dom' export default function Login() { const navigate = useNavigate() const login = () => { localStorage.setItem('token', '112222') navigate('/home') } return ( <div> <button onClick={login}>登录</button> </div> ) }
路由懒加载
import React, { Suspense } from 'react'
import { Routes, Route } from 'react-router-dom'
// 通过React.lazy函数配合import 函数实现按需导入模块
const Home = React.lazy(() => import('../Home'))
const Course = React.lazy(() => import('../Course'))
const Login = React.lazy(() => import('../Login'))
const News = React.lazy(() => import('../News'))
const NewsDetail = React.lazy(() => import('../NewsDetail'))
const Redirect = React.lazy(() => import('../Redirect'))
const NotFound = React.lazy(() => import('../NotFound'))
const JsCourse = React.lazy(() => import('../JsCourse'))
const VueCourse = React.lazy(() => import('../VueCourse'))
const ReactCourse = React.lazy(() => import('../ReactCourse'))
const AuthComponent = React.lazy(() => import('../AuthComponent'))
export default function MRoute() {
return (
// 使用Suspense组件包裹所有路由表
<Suspense>
// Routes替代了Switch
<Routes>
{/* element替代了component */}
<Route
path="/home"
element={
<AuthComponent>
<Home />
</AuthComponent>
}
></Route>
<Route path="/course" element={<Course />}>
{/* 嵌套路由 */}
{/* index匹配到的父路径 */}
<Route index element={<Redirect to="/course/js" />}></Route>
<Route path="js" element={<JsCourse />}></Route>
<Route path="vue" element={<VueCourse />}></Route>
<Route path="react" element={<ReactCourse />}></Route>
</Route>
{/* 新闻 */}
<Route path="/news" element={<News />}></Route>
<Route path="/login" element={<Login />}></Route>
{/* params形式 */}
<Route
path="/newsdetail/:id"
element={<NewsDetail></NewsDetail>}
></Route>
{/* 路由重定向 */}
<Route path="/" element={<Redirect to="/home" />}></Route>
{/* 404页面 */}
<Route path="*" element={<NotFound />}></Route>
</Routes>
</Suspense>
)
}
useRoutes钩子配置路由
-
路由懒加载组件封装
import React, { lazy, Suspense } from 'react' export default function LazyLoad(path) { const Element = lazy(() => import(`./${path}`)) return ( <Suspense> <Element /> </Suspense> ) }
-
使用useRoutes钩子将路由转成配置文件
import React, { Suspense } from 'react' import { useRoutes } from 'react-router-dom' import LazyLoad from '../LazyLoad' import Redirect from '../Redirect' export default function MRoute() { const element = useRoutes([ { path: '/', element: <Redirect to="/home"></Redirect>, }, { path: '/home', element: LazyLoad('Home'), }, { path: '/course', element: LazyLoad('Course'), children: [ { path: 'js', element: LazyLoad('JsCourse'), }, { path: 'vue', element: LazyLoad('VueCourse'), }, { path: 'react', element: LazyLoad('ReactCourse'), }, { path: '', element: <Redirect to="/course/js"></Redirect>, }, ], }, { path: '/news', element: LazyLoad('News'), }, { path: '/newsdetail/:id', element: LazyLoad('NewsDetail'), }, { path: '*', element: LazyLoad('NotFound') }, ]) return element }