Skip to content
返回构建教程

路由搭建

配置基于文件的路由,带布局、嵌套路由和类型化参数。

为什么

路由是应用骨架——每页、每布局、每导航过渡流经它。配置良好的路由给你嵌套布局(侧边栏 + 内容)、类型化路由参数(不再字符串解析)、每路由代码分割(更快初始加载)。基于文件路由(Next.js app router、TanStack Router)消除路由配置文件——文件系统即路由树,加页是建文件非编辑配置。类型化参数(useParams<{ id: string }>())编译时抓错参数名而非运行时渲染 undefined。

何时使用

应用有 ≥3 页时。约 1-2 小时。单页应用可跳过。

如何做

1. 用框架基于文件路由(Next.js app/、TanStack Router、Remix)
   - app/dashboard/users/[id]/page.tsx → /dashboard/users/:id
   - 布局:layout.tsx 包目录所有页

2. 用框架类型化参数类型化路由参数
   - Next.js:const { id } = useParams<{ id: string }>()
   - TanStack Router:生成 routeTree.gen.ts 全类型安全

3. 加根布局带共享外壳(头、尾、错误边界)
   - 此布局包每路由;保持最小(无数据获取)
   - 嵌套布局组合:root > dashboard > users > [id]

4. 每路由加 loading.tsx(Next.js)或 suspense fallback
   - 数据获取时显示骨架非空白页
   - 每路由代码分割,初始 bundle 仅含落地页

5. 每路由段加 not-found.tsx 和 error.tsx
   - 404 和错误应在应用外壳渲染,非白页

示例

// app/dashboard/users/[id]/page.tsx(Next.js app router)
import { useParams } from "next/navigation";
export default async function UserPage({ params }: { params: { id: string } }) {
  const user = await getUser(params.id);  // 类型化参数,无解析
  return <UserDetail user={user} />;
}

// app/dashboard/layout.tsx(嵌套布局)
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
  return (
    <div className="flex">
      <Sidebar />
      <main className="flex-1">{children}</main>
    </div>
  );
}

// app/dashboard/users/[id]/loading.tsx
export default function Loading() { return <UserDetailSkeleton />; }

// app/dashboard/users/[id]/error.tsx
export default function Error({ error }: { error: Error }) {
  return <ErrorBoundary error={error} />;
}

常见问题

  • ⚠parseInt 解析参数无验证,/users/abc 渲染 NaN 作 ID。
  • ⚠根布局放数据获取,每次导航全重取。
  • ⚠无加载状态,导航到数据重页显空白 2 秒。
  • ⚠根单一错误边界,一路由 bug 杀全应用。

最佳实践

  • ✓用类型化路由参数(Next.js:params 有类型;TanStack Router:全路径类型安全)编译时抓拼写错。
  • ✓布局薄——仅共享外壳,无数据获取——不阻塞导航。
  • ✓每数据获取路由加 loading.tsx,用户看骨架非空白页。
  • ✓共享布局的模态和条件用并行路由(Next.js @slot)。