news 2026/2/18 3:47:05

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/2/17 8:32:12

如何实现高精度多语言翻译?HY-MT1.5大模型镜像全解析

如何实现高精度多语言翻译&#xff1f;HY-MT1.5大模型镜像全解析 随着全球化进程加速&#xff0c;企业出海、跨语言内容生成和本地化服务对高质量机器翻译的需求日益增长。传统商业翻译API在术语一致性、上下文连贯性和格式保留方面存在明显短板&#xff0c;难以满足专业场景的…

作者头像 李华
网站建设 2026/2/16 17:25:23

单目深度估计技术解析:MiDaS的核心算法

单目深度估计技术解析&#xff1a;MiDaS的核心算法 1. 引言&#xff1a;从2D图像到3D空间感知的跨越 在计算机视觉领域&#xff0c;如何让机器“理解”真实世界的三维结构一直是一个核心挑战。传统方法依赖双目立体视觉或多传感器融合&#xff08;如LiDAR&#xff09;&#x…

作者头像 李华
网站建设 2026/2/16 8:39:00

多语言混合翻译新标杆|腾讯HY-MT1.5大模型镜像技术亮点全揭秘

多语言混合翻译新标杆&#xff5c;腾讯HY-MT1.5大模型镜像技术亮点全揭秘 在多语言内容呈指数级增长的今天&#xff0c;传统翻译系统正面临前所未有的挑战&#xff1a;用户输入中频繁出现中英夹杂、多语种嵌套、专业术语密集等复杂场景。为应对这一趋势&#xff0c;腾讯开源了…

作者头像 李华
网站建设 2026/2/16 19:53:17

AI万能分类器大赛复盘:冠军方案云端复现指南

AI万能分类器大赛复盘&#xff1a;冠军方案云端复现指南 引言&#xff1a;为什么你需要这个冠军方案&#xff1f; 参加过AI比赛的朋友都知道&#xff0c;从获奖论文到实际可运行的代码往往隔着"三天三夜"的环境配置。去年NeurIPS的万能分类器大赛冠军方案就是一个典…

作者头像 李华
网站建设 2026/2/17 1:23:04

单目深度估计技术对比:MiDaS vs 传统方法

单目深度估计技术对比&#xff1a;MiDaS vs 传统方法 1. 引言&#xff1a;为何单目深度估计是3D感知的关键一步 在计算机视觉领域&#xff0c;从2D图像中恢复3D空间结构一直是核心挑战之一。传统的深度感知依赖双目立体视觉&#xff08;如Stereo Vision&#xff09;、结构光或…

作者头像 李华
网站建设 2026/2/17 9:36:46

数组初始化的编译模式特征

文章目录数组初始化的编译模式特征1. **局部数组存储位置**2. **显式初始化部分**3. **未显式初始化部分的处理**4. **内存布局特征**5. **编译器优化特征**6. **初始化模式识别**7. **逆向识别线索**8: int Arr[10] {1}; 00F21DE0 mov dword ptr [Arr],1 00F21DE…

作者头像 李华