TanStack Router:Router 核心 API 全解——从路由树创建、createRouter 配置到类型体系
2026/9/14 11:41:36 网站建设 项目流程

TanStack Router:Router 核心 API 全解——从路由树创建、createRouter 配置到类型体系

【免费下载链接】router🤖 A client-first, server-capable, fully type-safe router and full-stack framework for the web (React and more).项目地址: https://gitcode.com/GitHub_Trending/ro/router

本文以 TanStack Router 官方 API 参考(docs/router/api/router.md)为主体,系统梳理@tanstack/react-router(及其同构的solid-routervue-router包)中 Router 层的全部 API:17 个函数、11 个组件、18 个 Hooks、24 个核心类型与 7 个已弃用 API。读完后,你将能够独立完成路由树的搭建、createRouter的完整配置、导航/预加载/错误处理等运行时操作,并理解每个 API 在 packages/router-core 中的实现落点。

一、API 全景:Router 模块由什么组成

Router API 总览页 将整套 API 划分为五类。它们共同构成一个"客户端优先、但同样具备服务端能力"的路由层,底层由框架无关的 router-core 包 承载核心逻辑(路由匹配、位置解析、加载生命周期等),各框架包(如 packages/react-router/src/index.tsx)在此基础上提供 React 绑定。

分类数量代表 API
函数17createRoutercreateRoutegetRouteApiredirectdefer
组件11<Link><Outlet><Await><Navigate><CatchBoundary>
Hooks18useNavigateuseLoaderDatauseParamsuseRouterState
类型24RouterOptionsRouterStateRouteOptionsToOptions
⚠️ 已弃用7Route类、Router类、RootRoute类等(见第五节)

函数 API 清单

  • 路由树构建:createFileRoutecreateLazyFileRoutecreateRootRoutecreateRootRouteWithContextcreateRoutecreateLazyRoute
  • 运行时创建:createRouter
  • 导航与控制流:redirectnotFoundisRedirectisNotFoundlazyRouteComponent
  • 路由掩码:createRouteMask
  • 搜索参数工具:retainSearchParamsstripSearchParams
  • 路由 API 绑定:getRouteApi
  • 异步数据:defer

组件 API 清单

<Link>(类型化链接)、<Outlet>(嵌套出口)、<Await>(消费defer的 Promise)、<Navigate>(声明式重定向)、<MatchRoute>(按目标渲染任意路由)、<ClientOnly>(仅客户端渲染)、<ErrorComponent><NotFoundComponent><CatchBoundary><CatchNotFound>(边界捕获)、<DefaultGlobalNotFound>(全局 404 兜底)。

Hooks 清单

useAwaiteduseBlockeruseCanGoBackuseChildMatchesuseLinkPropsuseLoaderDatauseLoaderDepsuseLocationuseMatchuseMatchRouteuseMatchesuseNavigateuseParentMatchesuseParamsuseRouteContextuseRouteruseRouterStateuseSearch

二、路由树构建 API:createRoute 与文件路由

2.1 createRoute 与 createRootRoute

createRoute 文档 定义了路由实例的创建方式:它接收一个RouteOptions对象并返回一个Route实例。路由实例被传入根路由的children,最终组成路由树,再交给createRouter。文档给出的标准示例:

import { createRoute } from '@tanstack/react-router' import { rootRoute } from './__root' const Route = createRoute({ getParentRoute: () => rootRoute, path: '/', loader: () => { return 'Hello World' }, component: IndexComponent, }) function IndexComponent() { const data = Route.useLoaderData() return <div>{data}</div> }

注意Route.useLoaderData()这种"静态绑定"的用法:路由对象本身就是该路由的 API 入口。而在文件路由场景下,getRouteApi(见 2.3)是不持有路由对象引用时的等价手段。

createRootRoute用于创建路由树的根节点;createRootRouteWithContext则是它的"带上下文"变体——当根路由声明了上下文类型时,createRouter必须提供对应的context(见第三节context属性)。

2.2 createFileRoute / createLazyFileRoute

文件路由是 TanStack Router 的默认工作流:路由由文件系统约定生成,@tanstack/router-plugin(packages/router-plugin)在构建期产出routeTree.gen文件,其中的Route对象由生成器注入id与类型。createFileRoute 文档 中的典型用法:

import { createFileRoute } from '@tanstack/react-router' export const Route = createFileRoute('/posts')({ loader: () => fetchPosts(), component: PostsComponent, })

createLazyFileRoute(文档)与createLazyRoute(文档)是懒加载变体:路由的组件与加载逻辑通过lazyRouteComponent(文档)包裹,实现按路由拆分 JS chunk。

2.3 getRouteApi:类型安全的全局路由 API

getRouteApi 文档 说明,它返回useParamsuseSearchuseRouteContextuseNavigateuseLoaderDatauseLoaderDeps这批常用 Hook 的类型安全预绑定版本——绑定到具体路由 ID 与注册的路由类型上,无需从组件作用域内导入路由对象:

import { getRouteApi } from '@tanstack/react-router' const routeApi = getRouteApi('/posts') export function PostsPage() { const posts = routeApi.useLoaderData() // ... }

在文件路由项目中,由于routeTree.gen由插件生成、id类型已知,getRouteApi('/posts')的字符串字面量参数与返回值都受到完整的类型约束——这正是"fully type-safe"主张在 API 层的直接体现。

三、createRouter 与 RouterOptions:配置路由器

3.1 createRouter 函数

createRouter 文档 定义:该函数接收一个RouterOptions对象(必填),返回一个Router实例。最小可运行示例:

import { createRouter, RouterProvider } from '@tanstack/react-router' import { routeTree } from './routeTree.gen' const router = createRouter({ routeTree, defaultPreload: 'intent', }) export default function App() { return <RouterProvider router={router} /> }

在 router-core 中,路由实例的构建与状态管理集中在 Router 核心实现,入口导出见 packages/router-core/src/index.ts;React 侧的挂载则通过 RouterProvider 实现 完成——RouterProvidercreateRouter返回实例与 React 渲染树之间的桥接。

3.2 RouterOptions 核心属性(节选与说明)

RouterOptions 文档 完整列举了所有配置项。以下按用途分组,给出类型、默认值与影响要点:

路由树与历史

  • routeTree(必填):AnyRoute,路由树本身。
  • history(可选):RouterHistory,未提供时内部新建一个createBrowserHistory实例,历史管理的实现位于 packages/history 包。
  • basepath(可选,默认/):整个路由器的挂载子路径,适合把路由实例挂到子路径下。
  • origin(可选):URL 解析使用的 origin。默认取浏览器 origin,服务端或匿名 origin 下为http://localhost。文档要求传入规范化 origin(如https://example.com,不带路径与尾斜杠);若手头是完整 URL,可用new URL(url).origin归一化后再传入。
  • caseSensitive(可选,默认false):为true时所有路由按大小写敏感匹配。
  • trailingSlash(可选,默认'never'):'always'补尾斜杠、'never'移除、'preserve'不修改。

搜索参数解析与严格模式

  • stringifySearch/parseSearch(可选):自定义搜索参数序列化/反序列化函数,默认分别为defaultStringifySearchdefaultParseSearch
  • search.strict(可选,默认false):控制任何validateSearch未声明的"未知搜索参数"的处理。false保留,true丢弃。
  • pathParamsAllowedCharacters(可选):Array<';' | ':' | '@' | '&' | '=' | '+' | '$' | ','>,声明哪些 URI 字符允许出现在 path 参数中而不被encodeURIComponent转义。

预加载与缓存

  • defaultPreload(可选,默认false):false表示不做任何预加载;'intent'在用户悬停链接或触发touchstart时预加载;'viewport'在链接进入视口时预加载;'render'在链接渲染进 DOM 时立即预加载。
  • defaultPreloadDelay(可选,默认50):intent 悬停/视口预加载前的延迟毫秒数;touch intent 立即预加载。
  • defaultStaleTime(默认0)、defaultPreloadStaleTime(默认30_000ms)、defaultPreloadGcTimedefaultGcTime(均默认 5 分钟):控制 loader 数据新鲜度与预加载/缓存条目的回收时机。
  • defaultStaleReloadMode(可选,默认'background'):过期 loader 数据的重新验证方式。'background'保持 stale-while-revalidate 行为;'blocking'则等待过期的 loader 重载完成后才让导航 resolve。

组件与等待态兜底

  • defaultComponent(默认Outlet):路由未提供component时的默认组件。
  • defaultErrorComponent(默认ErrorComponent)、defaultNotFoundComponent(默认NotFound):错误与 404 的默认渲染。
  • defaultPendingComponentdefaultPendingMs(默认1000)、defaultPendingMinMs(默认500):pending 组件及其显示/最短展示时间。
  • defaultOnCatch(可选):(error, errorInfo) => void,Router 内部 ErrorBoundary 捕获错误的默认处理器。
  • disableGlobalCatchBoundary(可选,默认false):true时禁用包裹所有路由匹配的兜底捕获边界,让未处理错误冒泡到浏览器顶层错误处理器——文档指出这主要用于测试工具、错误上报服务与调试场景。

安全:protocolAllowlist

  • protocolAllowlist(可选,默认DEFAULT_PROTOCOL_ALLOWLIST):允许出现在链接、重定向与导航中的 URL 协议数组,默认覆盖 Web 导航(http:https:)与常见浏览器安全动作(mailto:tel:)。不在白名单内的绝对 URL 会被拒绝,用于防御 XSS 类风险。文档强调该检查横跨<Link to="...">navigate({ to/href })redirect({ to/href })三类导航 API;条目必须匹配URL.protocol格式(小写带尾冒号),配置成'blob'(不带:)将无法放行blob:链接。
import { createRouter, DEFAULT_PROTOCOL_ALLOWLIST, } from '@tanstack/react-router' // 使用自定义白名单(替换默认值) const router = createRouter({ routeTree, protocolAllowlist: ['https:', 'mailto:'], }) // 或在默认白名单基础上扩展 const router = createRouter({ routeTree, protocolAllowlist: [...DEFAULT_PROTOCOL_ALLOWLIST, 'ftp:'], })

导航行为

  • defaultViewTransition(可选):true时导航通过document.startViewTransition()执行;传ViewTransitionOptions对象时可附带types数组走startViewTransition({ update, types }),浏览器不支持 types 时回退为普通 view transition;浏览器完全不支持该 API 时此选项被忽略。
  • defaultHashScrollIntoView(可选,默认true):位置写入历史后,是否将 id 与 hash 匹配的元素滚动到视口内;传对象则作为scrollIntoView的选项。
  • rewrite(可选):LocationRewrite,在浏览器 URL 与路由器内部 URL 之间做双向转换,详见 3.3。
  • context(可选;若根路由用createRootRouteWithContext()创建则必填):注入给整棵路由树的根上下文,避免逐路由提供。
  • dehydrate/hydrate(可选):SSR 脱水/注水时由用户扩展的序列化钩子,返回值会并入路由器的脱水状态。

404 与 URL 整形

  • notFoundMode(可选,默认'fuzzy'):'root' | 'fuzzy',控制找不到匹配路由时的行为。
  • notFoundRoute(已弃用):整棵路由树的默认 404 路由,可被各分支根路由的选项覆盖。
  • defaultStructuralSharing(可选,默认false):为细粒度选择器默认启用结构化共享。
  • defaultRemountDeps(可选):(opts) => any,依据routeIdsearchparamsloaderDeps计算组件重挂载依赖,返回值需 JSON 可序列化;返回值得变化时组件重挂载,默认导航后保持激活的组件不重挂载。例如remountDeps: ({ params }) => params可让所有路由组件在params变化时重挂载。

3.3 URL Rewrites:rewrite 配置详解

rewrite的类型形状(引自 RouterOptions 文档):

type LocationRewrite = { input?: LocationRewriteFunction output?: LocationRewriteFunction } type LocationRewriteFunction = (opts: { url: URL }) => undefined | string | URL
  • input:路由器解释 URL 之前的转换(浏览器 → 路由器);
  • output:写入浏览器历史之前的转换(路由器 → 浏览器)。

文档中的 i18n 前缀示例:

import { createRouter } from '@tanstack/react-router' const router = createRouter({ routeTree, rewrite: { input: ({ url }) => { // Strip locale prefix: /en/about → /about if (url.pathname.startsWith('/en')) { url.pathname = url.pathname.replace(/^\/en/, '') || '/' } return url }, output: ({ url }) => { // Add locale prefix: /about → /en/about url.pathname = `/en${url.pathname === '/' ? '' : url.pathname}` return url }, }, })

文档特别说明:当basepathrewrite同时配置时二者自动组合——input 阶段 basepath 剥离最先执行,output 阶段 basepath 回填最后执行。这一机制在 router-core 中的独立实现见 rewrite 模块。

3.4 Wrap / InnerWrap:渲染包装层

  • Wrap(可选):包裹整个路由器的组件,只应使用不产生 DOM 的 Provider 类组件,否则会引发 hydration 错误:
const router = createRouter({ Wrap: ({ children }) => { return <MyContext.Provider value={myContext}>{children}</MyContext> }, })
  • InnerWrap(可选):包裹路由器内部内容的组件,与Wrap的关键区别是它可以访问路由器上下文与 Hook:
const router = createRouter({ InnerWrap: ({ children }) => { const routerState = useRouterState() return ( <MyContext.Provider value={myContext}> {children} </MyContext> ) }, })

同样地,两者都只应承载 Provider 一类不渲染 DOM 的组件。

四、Router 实例方法:运行时能力

Router 类型文档 描述了实例的全部成员。核心提醒:router.state永远是最新的,但不是响应式的——在组件里读router.state不会触发重渲染,响应式读取必须使用useRouterState

成员签名要点说明
.update(newOptions: RouterOptions) => void用新选项更新路由实例
stateRouterState当前状态(非响应式)
.subscribe(eventType, fn) => () => void订阅 RouterEvent,返回退订函数
.matchRoutes(pathname, search?, opts?) => RouteMatch[]匹配路径与搜索参数;throwOnError: true时匹配错误会抛出
.buildLocation(opts: BuildNextOptions) => ParsedLocation构建待导航的位置对象
.commitLocation(location & { replace?, resetScroll?, hashScrollIntoView?, ignoreBlocker? }) => Promise<void>将位置提交到浏览器历史
.navigate(options: NavigateOptions) => Promise<void>导航到新位置
.invalidate(opts?: { filter?, sync?, forcePending? }) => Promise<void>失效选中的路由匹配代际并重跑加载生命周期
.clearCache(opts?: { filter? }) => void清除缓存的路由匹配与活动预加载
.load(opts?: { sync? }) => Promise<void>加载当前所有匹配,SSR 常用
.preloadRoute(opts: NavigateOptions) => Promise<RouteMatch[] \| undefined>预加载目标匹配
.loadRouteChunk(route: AnyRoute) => Promise<void>加载路由的 JS chunk
.matchRoute(dest: ToOptions, matchOpts?) => RouteMatch['params'] \| false匹配并返回参数
.dehydrate/.hydrate() => DehydratedRouter/(dehydrated) => voidSSR 状态序列化/反序列化

几个值得展开的要点:

  • buildLocation的 updater 语义paramssearchhashstate均可传true(沿用当前值)或传 updater 函数(以当前值为入参、返回新值);mask字段内嵌完整BuildNextOptions并额外支持unmaskOnReload
  • commitLocation默认行为replace默认false(用history.push);resetScroll默认true(提交后滚动复位到 0,0);hashScrollIntoView默认trueignoreBlocker默认false
  • .invalidate的语义边界:不传filter时失效所有已提交、缓存与在途的匹配代际;传filter时它作用于同一集合,选中一代即失效同一 match ID 的所有代际。失效会重跑beforeLoad,可复用的 loader 数据被标记为过期后走正常加载协议,而 match ID 不变时路由级context保持可复用。sync: true使返回的 Promise 在过期加载完成后才 resolve;forcePending: true让已有成功数据的路由也进入正常 pending 协议。
  • .loadstaleTime:文档明确警告router.load()尊重route.staleTime——新鲜的匹配保持新鲜,过期匹配会被重新验证;需要无视新鲜度强制重载时应改用router.invalidate()。其最常见用途是 SSR 场景:在流式渲染客户端之前确保当前路由的关键数据全部就绪。
  • .preloadRoute的推测性:活动预加载是推测性的,不会成为当前呈现的匹配;成功的 loader 数据可进入内存缓存,新鲜度遵循preloadStaleTime,闲置且超过preloadGcTime后可在后续缓存对账中被回收。每个预加载与导航各自执行beforeLoad链:后续 lane 可复用已结算的 loader 数据或并入进行中的 loader 工作,但从不复用beforeLoad上下文或已结算的 redirect/error/not-found 结果。该方法在服务端路由实例上同样可用,且不影响请求当前的位置与呈现匹配。

五、导航、控制流与搜索参数工具函数

5.1 redirect 与 notFound

redirect在 loader/beforeLoad中抛出以触发类型安全重定向;isRedirect是其守卫函数。notFound抛出 404 语义的错误;isNotFound对应判断。这四个函数在 router-core 中分别对应 redirect 实现 与 not-found 实现。

5.2 retainSearchParams 与 stripSearchParams

retainSearchParamsstripSearchParamssearchupdater 的辅助:前者只替换指定键、保留其余搜索参数,后者剔除指定键、保留其余。它们让"改一个参数而不打乱 URL 里其它参数"成为一行代码的事。

5.3 defer 与 :流式渲染

defer在 loader 中返回一组延迟 Promise;配套的<Await>组件与useAwaitedHook 负责消费它们,实现"首屏关键数据先渲染、非关键数据流式补全"。defer的运行时支持位于 packages/router-core/src/defer.ts,服务端流式渲染的入口在 router-core 的 ssr 目录。

六、路由掩码:createRouteMask

createRouteMask 文档 定义:该函数创建一个RouteMask配置对象,供RouterOptions.routeMasks使用。"路由掩码"指以与配置匹配不同的路径来显示某条路由——典型场景是弹窗:用户看到的是/photos/$photoId/modal,但把链接分享出去或刷新后,落地的是弹窗内容本身而非弹窗上下文。

import { createRouteMask, createRouter } from '@tanstack/react-router' const photoModalToPhotoMask = createRouteMask({ routeTree, from: '/photos/$photoId/modal', to: '/photos/$photoId', params: true, }) const router = createRouter({ routeTree, routeMasks: [photoModalToPhotoMask], })

与掩码配合的两个路由器级选项:routeMasks(掩码数组)与unmaskOnReload(默认falsetrue时页面刷新默认解除掩码;可在单个 mask 或单次导航的NavigateOptions.mask.unmaskOnReload上覆盖)。

七、类型体系

总览页 列出的 24 个类型是整套 API 的类型契约,按职责可分为四组:

  • 路由器契约RouterRouterOptionsRouterStateRouterEventsRegister(模块级类型注册入口)。
  • 路由与匹配RouteRouteOptionsRouteApiRouteMatchRouteMaskMatchRouteOptionsUseMatchRouteOptionsAsyncRouteComponent
  • 位置与历史ParsedLocationHistoryStateParsedHistoryState
  • 导航与错误ToOptionsToMaskOptionsNavigateOptionsLinkOptions/LinkOptions/LinkProps/ActiveLinkOptionsViewTransitionOptionsRedirectNotFoundError

这些类型在源码层面的公共入口是 router-core 的 typePrimitives 模块 与总 index 导出;框架包(如 packages/react-router/src/index.tsx)会将其连同框架绑定一起再导出。

八、已弃用 API 与迁移方向

总览页 标注了 7 个 ⚠️ Deprecated 条目:FileRoute类、Route类、Router类、RouteApi类、RootRoute类、NotFoundRoute类 与rootRouteWithContext函数(文档)。

从文档结构可以确认,当前版本的 API 设计已全部转向函数式:类被createFileRoute/createRoute/createRootRoute/createRootRouteWithContext等工厂函数取代,routeRouteWithContextcreateRootRouteWithContext取代。新代码应直接采用函数式 API,避免触碰上述类。

九、API 与实现的对应关系

API文档源码落点(router-core 为框架无关核心)
createRouter/ Router 实例createRouterFunction.mdpackages/router-core/src/router.ts、packages/router-core/src/root.ts
createRoute/ 路由实例createRouteFunction.mdpackages/router-core/src/route.ts
文件路由(React 绑定)createFileRouteFunction.mdpackages/react-router/src/fileRoute.ts
redirect/notFoundredirectFunction.mdpackages/router-core/src/redirect.ts、packages/router-core/src/not-found.ts
rewriteRouterOptionsType.mdpackages/router-core/src/rewrite.ts
deferdeferFunction.mdpackages/router-core/src/defer.ts
<Link>linkComponent.mdpackages/router-core/src/link.ts、packages/react-router/src/link.tsx
useNavigate/useRouterStateuseNavigateHook.mdpackages/router-core/src/useNavigate.ts、packages/react-router/src/useRouterState.tsx

从源码结构看,router-core承担了匹配(matches 模块)、位置解析(location 模块)、搜索参数中间件(searchMiddleware 模块)、结构化共享(structuralSharing 模块)等横切能力,各框架包只做渲染与响应式绑定——这解释了为何同一套 API 参考可以覆盖 React、Solid、Vue 三种前端。

十、小结

  • 路由树由createRootRoute/createRoute(或文件路由下的createFileRoute/createLazyFileRoute)构建,最终交给createRouter({ routeTree, ... })装配成可运行的路由器,RouterProvider负责将其挂载进应用;
  • RouterOptions是全部行为的配置面:预加载策略(defaultPreload/defaultPreloadDelay)、缓存新鲜度(staleTime系列)、404 策略(notFoundMode)、安全边界(protocolAllowlist)、URL 整形(basepath/rewrite/trailingSlash)与 SSR 序列化(dehydrate/hydrate)都从这里配置;
  • 运行时导航能力集中在 Router 实例方法:navigate/buildLocation/commitLocation处理位置流转,invalidate/clearCache/preloadRoute/load处理数据与缓存生命周期,subscribe暴露完整事件流;
  • getRouteApi提供了不依赖组件作用域的类型安全 Hook 绑定,与retainSearchParams/stripSearchParamsdefer/<Await>createRouteMask一起,覆盖了搜索参数、流式数据与弹窗路由三类高频实战场景;
  • 类式 API 已全部弃用,编写新代码时直接使用第八节之前的函数式 API 即可。

【免费下载链接】router🤖 A client-first, server-capable, fully type-safe router and full-stack framework for the web (React and more).项目地址: https://gitcode.com/GitHub_Trending/ro/router

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询