React学习———React Router

React Router

React Router 是 React 应用中用于管理路由的流行库,它允许你在单页应用(SPA)中实现导航和页面切换而无需重新加载页面。

安装

bash 复制代码
npm install react-router-dom

核心组件

<BrowserRouter>
  • 使用HTML5的历史记录API(pushStatereplaceStatepopstate事件)来保持UIURL的同步。
  • 通常包裹在应用的根组件 中,提供基于浏览器历史记录的路由功能。
js 复制代码
import { BrowserRouter } from 'react-router-dom'
function App(){
	return (
		<BrowserRouter >
			{/* 其他组件 */}
		</BrowserRouter >
	)
}
<HashRouter>
  • 通过监听浏览器的hashchange事件来检测路由变化,因为hash部分不会被服务器解析,所以无需服务器支持。
  • 使用方法和BrowserRouter一致,适合静态部署 或后端不支持history路由的场景
<Routes><Route>
  • <Routes>:包裹所有路由规则
  • <Route>:定义单个路由,通过path属性指定URL路径、element属性/component属性指定要渲染的组件
js 复制代码
import { Routes, Route } from 'react-router-dom'
function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
    </Routes>
  );
}
<Link>
  • 用于应用内导航,替代<a>标签实现导航,生成一个不会导致页面重新加载的链接,避免页面刷新
js 复制代码
import { Link } from 'react-router-dom'
function Navbar() {
 return (
   <nav>
     <Link to="/" >Home</Link>
   </nav>
 );
}
<Navigate>
  • 用于编程式导航或重定向,例如:当用户访问某个路径时,可以自动重定向到另一个路径
js 复制代码
<Route path="/old-path" element={<Navigate to="/new-path" />} />

动态路由

  • 通过在路由path中使用冒号:参数名定义参数
js 复制代码
import { Route, Routes } from 'react-router-dom'
import User from './User'
<Routes>
	// 这样 /user/123、/user/abc都会匹配该路由
	<Route path="/user/:id" element={<User />} />
</Routes>
  • 使用*通配符匹配任意路径
js 复制代码
import { Route, Routes } from 'react-router-dom'
import User from './User'
<Routes>
	// 这样 /user/xxx/yyy都会匹配该路由
	<Route path="/user/*" element={<User />} />
</Routes>
  • 获取URL参数: 通过useParams获取动态路径参数
js 复制代码
import { useParams } from 'react-router-dom'
function User(){
	const { id } = useParams()
	return <div>用户ID:{id}</div>
}
  • 获取查询参数:通过useSearchParams获取和修改查询参数
js 复制代码
import { useSearchParams} from 'react-router-dom'
function SearchPage(){
	const [searchParams, setSearchParams] = useSearchParams();
  	const keyword = searchParams.get("q"); // 例如 /search?q=react
	return (
    <input
      value={keyword || ""}
      onChange={(e) => setSearchParams({ q: e.target.value })}
    />
  );
}

嵌套路由

  • 在父路由中定义子路由,用<Outlet>指定子路由渲染位置
js 复制代码
// 父组件---使用 <Outlet> 指定子组件的位置:
function Dashboard(){
	return (
		<div>
			<h1>Dashboard</h1>
			{/* 子路由内容在此渲染 */}
			<Outlet /> 
		</div>
	)
}

// 通过 <Route> 的嵌套结构实现:
<Route path="/dashboard" element={<Dashboard />}>
  <Route path="stats" element={<Stats />} />
  <Route path="settings" element={<Settings />} />
</Route>

编程试导航

  • 使用useNavigate钩子进行跳转
js 复制代码
import { useNavigate } from "react-router-dom";
function LoginButton() {
  const navigate = useNavigate();
  return (
    <button onClick={() => {
        // 跳转到指定路径
        navigate("/dashboard");
        // 替换历史记录(无后退)
        navigate("/dashboard", { replace: true });
        // 带状态传递
        navigate("/dashboard", { state: { from: "login" } });
      }}>
      Login
    </button>
  );
}

路由懒加载(代码分割)

  • 使用React.lazySuspense优化性能
js 复制代码
import React, { lazy, Suspense } from 'react'
import { Routes, Route } from 'react-router-dom'

const Home = lazy(() => import('./home.jsx'))
function App(){
	return (
		// fallback属性可以自定义加载时的占位内容(如loading动画)
		<Suspense fallback={<div>加载中。。。</div>}>
			<Routes>
				<Route path='/' element={<Home />}></Route>
			</Routes>
		</Suspense>
	)
}

高阶组件实现权限控制

  • 高阶组件是一种用于复用组件逻辑的高级技术;采用函数接收组件,返回新组件的模式。
js 复制代码
function PrivateRoute({children}){
	consr isAdmin = checkAuth()
	return isAdmin ? children : <Navigate to='/login' />
}

<Route path='/admin' element={<PrivateRoute>
	<Home />
</PrivateRoute>} />

数据加载(v6.4+)

  • 使用loaderuseLoaderData路由加载时预取数据
js 复制代码
// 定义路由时配置loader
const router = createBrowserRouter([
	{
		path: '/user/:userId',
		element: <User />
		loader: async ({ params }) => {
			// 根据URL传递的数据进行接口请求
			const res = await fetch(`/api/users/${params.userId}`)
			return res.json()
		}
	}
])

// 组件中获取数据
import { useLoaderData } from 'react-router-dom'
function User(){
	// 直接获取 loader 返回的数据
	const userData = useLoaderData(); 
  	return <div>{userData.name}</div>;
}

路由配置简单demo

  • src目录下创建一个router文件夹管理路由列表
js 复制代码
// 用于编程式导航 重定向
import { Navigate } from 'react-router-dom'
// 高阶组件实现权限控制
import AuthRoute from '@/components/AuthRoute'
// 界面排版组件
import Layout from '@/pages/Layout'
import Admin from '@/pages/Admin'
import Login from '@/pages/Login'

export const routesList = [
	{
        path: '/',
        element: <Navigate to="/home" />
    },
    {
        path: '/login',
        element: <Login />
    },
    {
        path: '/admin',
        element: <Admin />
        children: [
        	{ { path: 'optical', element: <AuthRoute ><OpticalManage /></AuthRoute> }, }
        ]
    },
]
  • App.tsx进行路由配置
js 复制代码
interface PageRoute{
  path: string,
  element: React.ReactNode,
  children?: PageRoute[]
}

// 使用递归实现 Route 的渲染
function renderRoutes(routes: PageRoute[]) {
  return routes.map(({ path, element, children }, index) => (
    <Route key={path || index} path={path} element={element}>
      {children && renderRoutes(children)}
    </Route>
  ))
}
function App() {
  const loading = useSelector<RootState, boolean>(state => state.head.loading)
  return (
    <div className="app-view">
      {loading && <Loading />}
      <Routes>
        { renderRoutes(routesList) }
      </Routes>
    </div>
  )
}

export default App
常见坑
  • 箭头函数体{}时,必须显示写return
js 复制代码
function renderRoutes(routes: PageRoute[]) {
  return routes.map(({ path, element, children }, index) => {
   return	<Route key={path || index} path={path} element={element}>
      {children && renderRoutes(children)}
    </Route>
  });
}
  • ()时,直接返回表达式
js 复制代码
function renderRoutes(routes: PageRoute[]) {
  return routes.map(({ path, element, children }, index) => (
    <Route key={path || index} path={path} element={element}>
      {children && renderRoutes(children)}
    </Route>
  ))
}
相关推荐
哎哟喂_!17 分钟前
Node.js 同步加载问题详解:原理、危害与优化策略
前端·chrome·node.js
__BMGT()18 分钟前
C++ QT图片查看器
前端·c++·qt
关于不上作者榜就原神启动那件事31 分钟前
Java基础学习
java·开发语言·学习
OK_boom1 小时前
React-useRef
javascript·react.js·ecmascript
未来之窗软件服务1 小时前
solidwors插件 开发————仙盟创梦IDE
前端·javascript·数据库·ide·仙盟创梦ide
小黑_深呼吸1 小时前
Prometheus实战教程:k8s平台-Mysql监控案例
运维·学习·kubernetes·prometheus
Varpb1 小时前
【vue】【环境配置】项目无法npm run serve,显示node版本过低
前端·vue.js·npm
读心悦1 小时前
CSS 溢出内容处理、可见性控制与盒类型设置深度解析
前端·css
Minyy111 小时前
Vue3指令(二)--v-text、v-html数据渲染,计算属性
前端·javascript·vue.js·前端框架·vue·html
个人开发-胡涂涂2 小时前
ECMAScript标准:JavaScript的核心
前端·javascript·ecmascript