当前位置: 首页 > news >正文

React 中除了react-router还有哪些路由方案

在用React开发时,常用的路由是react-router ,但除此之外,还有两个路由方案,因为他们具备 react-router 没有的特性。

1. @tanstack/router

1.1. 主要特性

  • 100% 推断的 TypeScript 支持

  • 类型安全的导航

  • 嵌套路由和布局路由

  • 内置的路由加载器,带有 SWR 缓存

  • 为客户端数据缓存设计(如 TanStack Query、SWR 等)

  • 自动路由预取

  • 异步路由元素和错误边界

  • 基于文件的路由生成

  • 类型安全的 JSON 优先搜索参数状态管理 API

  • 路径和搜索参数模式验证

  • 搜索参数导航 API

  • 自定义搜索参数解析器/序列化器支持

  • 搜索参数中间件

  • 路由匹配/加载中间件

1.2. 基础使用示例

import React, { StrictMode } from 'react'
import ReactDOM from 'react-dom/client'
import {Outlet,RouterProvider,Link,createRouter,createRoute,createRootRoute} from '@tanstack/react-router'import { TanStackRouterDevtools } from '@tanstack/router-devtools'const rootRoute = createRootRoute({component: () => (<><div className="p-2 flex gap-2"><Link to="/" className={[&.active]:font-bold">Home</Link>{' '}<Link to="/about" className={[&.active]:font-bold">About</Link></div><hr /><Outlet /><TanStackRouterDevtools /></>),
})const indexRoute = createRoute({getParentRoute: () => rootRoute,path: '/',component: function Index() {return (<div className="p-2"><h3>Welcome Home!</h3></div>)},
})const aboutRoute = createRoute({getParentRoute: () => rootRoute,path: '/about',component: function About() {return <div className="p-2">Hello from About!</div>},
})const routeTree = rootRoute.addChildren([indexRoute, aboutRoute])
const router = createRouter({ routeTree })declare module '@tanstack/react-router' {interface Register {router: typeof router}
}const rootElement = document.getElementById('app')!
if (!rootElement.innerHTML) {const root = ReactDOM.createRoot(rootElement)root.render(<StrictMode><RouterProvider router={router} /></StrictMode>,)
}

1.3. 原理浅析

@tanstack/router 的实现原理与 react-router 类似,关注的概念也完全相同,可以理解为它站在 react-router 的肩膀上,在某些细节上做了增强。

历史记录的实现:https://github.com/TanStack/router/blob/main/packages/history/src/index.ts

Router 入口:https://github.com/TanStack/router/blob/main/packages/react-router/src/link.tsx

2. wouter

2.1. 主要特性

  • 最小依赖,压缩后仅 2.1 KB,对比 React Router 的 18.7 KB。

  • 同时支持 React 和 Preact。

  • 没有顶级的 <Router /> 组件,它是完全可选的。

  • 模仿 React Router 的最佳实践,提供熟悉的 Route、Link、Switch 和 Redirect 组件。

  • 拥有基于 hook 的 API,用于更细粒度地控制路由:useLocation、useRoute 和 useRouter。

2.2. 基础使用示例

import { Link, Route, Switch } from "wouter";const App = () => (<><Link href="/users/1">Profile</Link><Route path="/about">About Us</Route>{/* Routes below are matched exclusively - the first matched route gets rendered*/}<Switch><Route path="/inbox" component={InboxPage} /><Route path="/users/:name">{(params) => <>Hello, {params.name}!</>}</Route>{/* Default route in a switch */}<Route>404: No such page!</Route></Switch></>
);

2.3. 原理浅析

对于不同路由历史与定位信息的封装。

  • https://github.com/molefrog/wouter/blob/v3/packages/wouter/src/use-browser-location.js

  • https://github.com/molefrog/wouter/blob/v3/packages/wouter/src/use-hash-location.js

  • https://github.com/molefrog/wouter/blob/v3/packages/wouter/src/memory-location.js

import { parse as parsePattern } from "regexparam";
import {useBrowserLocation,useSearch as useBrowserSearch,
} from "./use-browser-location.js";
import {useRef,useContext,createContext,isValidateElement,cloneElement,createElement as h,Fragment,forwardRef,useIsomorphicLayoutEffect,useEvent,
} from "./react-deps.js";
import { absolutePath, relativePath, unescape, stripQm } from "./paths.js";// 定义默认的 Router 对象
const defaultRouter = {hook: useBrowserLocation,searchHook: useBrowserSearch,parser: parsePattern,base: "",ssrPath: undefined,ssrSearch: undefined,hrefs: (x) => x,
};// 创建一个 Router 上下文,提供给应用中的其他部分使用
const RouterCtx = createContext(defaultRouter);// 获取最近的父级 router
export const useRouter = () => useContext(RouterCtx);// 创建一个参数上下文,提供给 `useParams()` 使用,以获取匹配的参数
const ParamsCtx = createContext({});
export const useParams = () => useContext(ParamsCtx);// 内部版本的 useLocation 函数,避免多余的 useRouter 调用
const useLocationFromRouter = (router) => {const [location, navigate] = router.hook(router);return [unescape(relativePath(router.base, location)),useEvent((to, navOpts) => navigate(absolutePath(to, router.base), navOpts)),];
};// 使用 useRouter 获取当前的 location
export const useLocation = () => useLocationFromRouter(useRouter());// 获取当前搜索参数并返回
export const useSearch = () => {const router = useRouter();return unescape(stripQm(router.searchHook(router)));
};// 路由匹配函数
export const matchRoute = (parser, route, path, loose) => {const { pattern, keys } =route instanceof RegExp? { keys: false, pattern: route }: parser(route || "*", loose);const result = pattern.exec(path) || [];const [base, ...matches] = result;return base !== undefined? [true,() => {const groups =keys !== false? Object.fromEntries(keys.map((key, i) => [key, matches[i]])): result.groups;let obj = { ...matches };groups && object.assign(obj, groups);return obj;},...(loose ? [$base] : []),]: [false, null];
};// 使用 useRouter 获取路由,并匹配路径
export const useRoute = (pattern) =>matchRoute(useRouter().parser, pattern, useLocation()[0]);// Router 组件,用于提供自定义路由上下文
export const Router = ({ children, ...props }) => {const parent_ = useRouter();const parent = props.hook ? defaultRouter : parent_;let value;const [path, search] = props.ssrPath?.split("?") ?? [];if (search) (props.ssrSearch = search), (props.ssrPath = path);props.hrefs = props.hrefs ?? props.hook?.hrefs;let ref = useRef({}),prev = ref.current,next = prev;for (let k in parent) {const option =k === "base"? parent[k] + (props[k] || ""): props[k] || parent[k];if (prev === next && option !== next[k]) {ref.current = next = { ...next };}next[k] = option;if (option !== parent[k]) value = next;}return h(RouterCtx.Provider, { value, children });
};// 渲染 Route 组件,根据 props 提供不同渲染逻辑
const h_route = ({ children, component }, params) => {if (component) return h(component, { params });return typeof children === "function" ? children(params) : children;
};// Route 组件,用于匹配路径并渲染对应组件
export const Route = ({ path, nest, match, ...renderProps }) => {const router = useRouter();const [location] = useLocationFromRouter(router);const [matches, params, base] =match ?? matchRoute(router.parser, path, location, nest);if (!matches) return null;const children = base? h(Router, { base }, h_route(renderProps, params)): h_route(renderProps, params);return h(ParamsCtx.Provider, { value: params, children });
};
http://www.dtcms.com/a/251338.html

相关文章:

  • Zustand:小而美的React状态管理库详解
  • React 动态路由的使用和实现原理
  • 【Qt】Qt 基础
  • Kafka源码P2-生产者缓冲区
  • 软考 系统架构设计师系列知识点之杂项集萃(89)
  • [NLP]课程期末知识点总结
  • SAP-增删改查
  • 分布式数据库中间件-Sharding-JDBC
  • Some chunks are larger than 500 KiB after minification. Consider
  • 2025CVPR最佳论文系列
  • 机器学习实验报告4-Logistic 回归算法
  • Java + Spring Boot 后端防抖实现方案
  • Apache Iceberg与Hive集成:分区表篇
  • 鸿蒙智行5月全系交付新车破4.4万辆,销量再创新高
  • HarmonyOS 探秘手记:我在 “鸿蒙星球” 的第一天
  • 2 Studying《Arm A715 Technical Reference Manual》
  • Maven在依赖管理工具方面的内容
  • 向量外积与秩1矩阵的关系
  • 【项目实训】【项目博客#08】HarmonySmartCodingSystem系统前后端知识图谱与可视化实现(5.12-6.1)
  • Spring Cloud 所有组件全面总结
  • 传统数据仓库正在被 Agentic AI 吞噬
  • 快速取模指数算法:密码学的核心引擎
  • 正整数的正向分解
  • Git里面Stash Changes和UnStash Changes使用
  • ​​WSL2 (Ubuntu)​​ 中安装 ​​CUDA 12.9​​ 的详细教程
  • Spring Boot Web开发
  • ansible变量
  • springboot项目启动报错:spring boot application in default package
  • ansible模块使用实践
  • 如何在现有的分科、分纲、分目、分类的知识体系下构建根茎式心智