news 2026/7/30 16:02:55

TanStack Router 实战:如何构建经典的“左侧菜单 + 右侧内容”后台布局

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
TanStack Router 实战:如何构建经典的“左侧菜单 + 右侧内容”后台布局

在开发企业级后台管理系统(Admin Dashboard)时,“左侧固定菜单 + 右侧动态内容”是最经典的布局模式。同时,我们通常还需要一个独立的登录页面,它不包含菜单栏,而是全屏显示。

在使用TanStack Router这种基于文件系统的路由库时,如何优雅地实现这两种截然不同的布局共存,且保持 URL 简洁(例如访问/users而不是/admin/users)?

答案就是使用无路径布局路由 (Pathless Layout Route)。本文将带你一步步落地这个架构。

1. 核心概念:什么是无路径布局?

在 TanStack Router 中,如果你希望创建一个“包裹器”组件(比如包含侧边栏的 Layout),但不希望它在 URL 中增加一层路径,你需要在文件名加一个下划线前缀_

  • routes/admin.tsx: 会生成/admin/...的 URL 路径。
  • routes/_layout.tsx:不会生成 URL 路径,它只是一个逻辑上的包裹层。

利用这个特性,我们可以实现:

  • /login-> 渲染独立的登录页。
  • /-> 渲染_layout(带菜单) -> 渲染index(仪表盘)。
  • /users-> 渲染_layout(带菜单) -> 渲染users(用户列表)。

2. 推荐的文件结构

这是实现该架构的最佳目录结构。请注意_layout文件夹的使用:

Plaintext

体验AI代码助手

代码解读

复制代码

src/ └── routes/ ├── __root.tsx # 根组件 (通常只放 Context/DevTools) ├── login.tsx # 独立的登录页 (无菜单) ├── _layout.tsx # ✨ 核心:后台布局主文件 └── _layout/ # ✨ 核心:布局内部的子页面目录 ├── index.tsx # 对应 URL: / (仪表盘) ├── users.tsx # 对应 URL: /users └── settings.tsx # 对应 URL: /settings

⚠️ 必须注意:如果你创建了src/routes/_layout/index.tsx,请务必删除项目根目录下的src/routes/index.tsx,否则会报“路由冲突”错误。

3. 代码实现

第一步:编写布局容器 (src/routes/_layout.tsx)

这是整个架构的骨架。我们需要在这里划分左右区域,并放置<Outlet />

TypeScript

体验AI代码助手

代码解读

复制代码

import { createFileRoute, Outlet, Link } from '@tanstack/react-router' export const Route = createFileRoute('/_layout')({ component: AdminLayout, }) function AdminLayout() { return ( <div className="flex h-screen w-full bg-gray-100"> {/* --- 左侧侧边栏 --- */} <aside className="w-64 bg-gray-900 text-white flex flex-col shadow-lg"> <div className="p-6 text-xl font-bold border-b border-gray-800"> Admin System </div> <nav className="flex-1 p-4 space-y-2"> <MenuLink to="/" label="仪表盘" /> <MenuLink to="/users" label="用户管理" /> <MenuLink to="/settings" label="系统设置" /> </nav> </aside> {/* --- 右侧内容区域 --- */} <main className="flex-1 flex flex-col overflow-hidden"> {/* 顶部通栏 (Header) */} <header className="h-16 bg-white shadow-sm flex items-center px-6"> <span className="text-gray-500">面包屑 / 顶部导航</span> </header> {/* 页面内容滚动区 */} <div className="flex-1 overflow-auto p-6"> {/* ✨✨✨ 关键点:子路由渲染出口 ✨✨✨ */} <Outlet /> </div> </main> </div> ) } // 封装一个简单的菜单组件,自动处理高亮 function MenuLink({ to, label }: { to: string; label: string }) { return ( <Link to={to} className="block px-4 py-2 rounded transition-colors hover:bg-gray-800" // 激活时的样式 activeProps={{ className: 'bg-blue-600 text-white shadow' }} // 首页路由需要精确匹配,防止所有页面都高亮它 activeOptions={{ exact: to === '/' }} > {label} </Link> ) }

第二步:编写子页面

子页面文件放在src/routes/_layout/目录下。

仪表盘 (src/routes/_layout/index.tsx):

TypeScript

体验AI代码助手

代码解读

复制代码

import { createFileRoute } from '@tanstack/react-router' // 注意:参数必须匹配文件路径 export const Route = createFileRoute('/_layout/')({ component: () => ( <div className="bg-white p-8 rounded shadow"> <h1 className="text-2xl font-bold mb-4">欢迎回来</h1> <p>这里是仪表盘的核心数据区域。</p> </div> ), })

用户管理 (src/routes/_layout/users.tsx):

TypeScript

体验AI代码助手

代码解读

复制代码

import { createFileRoute } from '@tanstack/react-router' export const Route = createFileRoute('/_layout/users')({ component: () => <div>用户列表管理界面</div>, })

第三步:独立的登录页 (src/routes/login.tsx)

因为它不在_layout文件夹内,所以它不会继承左侧菜单。

TypeScript

体验AI代码助手

代码解读

复制代码

import { createFileRoute } from '@tanstack/react-router' export const Route = createFileRoute('/login')({ component: () => ( <div className="h-screen w-full flex items-center justify-center bg-gray-200"> <div className="p-10 bg-white rounded-lg shadow-xl"> <h1 className="text-2xl font-bold">请登录</h1> {/* 登录表单... */} </div> </div> ), })

4. 常见坑点与排查 (Troubleshooting)

在搭建这套架构时,90% 的开发者会遇到以下三个问题:

坑点一:路由冲突 (Conflicting configuration paths)

现象:终端报错 Conflicting configuration paths were found for the following routes: "/", "/"。

原因:你的旧文件 src/routes/index.tsx 和新文件 src/routes/_layout/index.tsx 都试图代表根路径 /。

解决:直接删除 src/routes/index.tsx。

坑点二:右侧一片空白

现象:能看到左侧菜单,URL 也没错,但右边内容区是空的。

原因:你忘记在 _layout.tsx 里写 了。

解决:在

标签内部添加 组件。

坑点三:TS 爆红波浪线

现象:刚创建 _layout.tsx 时,createFileRoute('/_layout') 处提示类型错误。

原因:TanStack Router 还没来得及生成类型定义。

解决:

  1. 保存文件(即使有错)。
  2. 等待终端显示生成完成。
  3. 如果还没好,按Cmd/Ctrl + Shift + P->TypeScript: Restart TS Server

5. 总结

通过使用_layout.tsx(无路径布局),我们成功实现了:

  1. 结构清晰:后台页面集中管理,与登录页物理隔离。
  2. URL 简洁:用户访问的是/users而非繁琐的/layout/users
  3. 开发高效:配合<Outlet />和自动高亮的<Link />,几分钟就能搭好骨架。

这套方案是目前 TanStack Router 构建中后台系统的最佳实践。


原文:https://juejin.cn/post/7594051311647621129

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/29 16:56:10

智能制造为什么要实现EMS和MES的集成

在智能制造成熟度咨询和评估过程中&#xff0c;我们发现许多企业的能源管理系统EMS仅实现了对重点能耗的实时、在线的数据采集与可视化监控&#xff0c;但数据孤立于生产系统&#xff08;MES&#xff09;&#xff0c;没有实现EMS和MES的集成。首先科普&#xff1a;什么是EMS&am…

作者头像 李华
网站建设 2026/7/29 11:17:18

MiDaS模型性能测试:CPU推理速度

MiDaS模型性能测试&#xff1a;CPU推理速度 1. 引言&#xff1a;AI 单目深度估计的现实价值 在计算机视觉领域&#xff0c;从单张2D图像中恢复3D空间结构一直是极具挑战性的任务。传统方法依赖多视角几何或激光雷达等硬件支持&#xff0c;成本高且部署复杂。而近年来&#xf…

作者头像 李华
网站建设 2026/7/27 4:32:06

如何高效查找文献:掌握<|关键词|>的实用方法与技巧

盯着满屏的PDF&#xff0c;眼前的外语字母开始跳舞&#xff0c;脑子里只剩下“我是谁、我在哪、这到底在说什么”的哲学三问&#xff0c;隔壁实验室的师兄已经用AI工具做完了一周的文献调研。 你也许已经发现&#xff0c;打开Google Scholar直接开搜的“原始人”模式&#xff…

作者头像 李华
网站建设 2026/7/29 5:34:47

如何利用类似谷歌搜索文献的工具高效查找学术资源与研究资料

盯着满屏的PDF&#xff0c;眼前的外语字母开始跳舞&#xff0c;脑子里只剩下“我是谁、我在哪、这到底在说什么”的哲学三问&#xff0c;隔壁实验室的师兄已经用AI工具做完了一周的文献调研。 你也许已经发现&#xff0c;打开Google Scholar直接开搜的“原始人”模式&#xff…

作者头像 李华
网站建设 2026/7/24 3:11:36

【YOLOv8改进】基于tood_x101-64x4d_fpn_ms-2x_coco的卡车过载检测与分类_1

1. YOLOv8改进&#xff1a;基于tood_x101-64x4d_fpn_ms-2x_coco的卡车过载检测与分类 1.1. 研究背景与意义 在物流运输行业中&#xff0c;卡车超载是一个普遍存在的安全问题&#xff0c;不仅会对道路桥梁造成损害&#xff0c;还极易引发交通事故。传统的超载检测方法主要依赖…

作者头像 李华
网站建设 2026/7/26 7:11:29

别再问了!高校网络安全 36 个名词,一篇看懂不踩坑

在高校数字化转型加速的当下&#xff0c;校园网不再只是简单的上网通道&#xff0c;而是承载教学科研、学生管理、财务数据等核心信息的关键载体。随之而来的网络安全风险也愈发复杂&#xff0c;从黑客攻击、数据泄露到系统瘫痪&#xff0c;每一个隐患都可能影响高校正常运转。…

作者头像 李华