本指南将带你了解 @feoe/fs-router 的基础使用方法。
@feoe/fs-router 使用文件系统作为路由的基础,遵循以下约定:
src/routes/
├── layout.tsx # 根布局组件
├── page.tsx # 首页 (/)
├── about/
│ └── page.tsx # /about 页面
├── user/
│ ├── layout.tsx # 用户页面布局
│ ├── page.tsx # /user 页面
│ └── [id]/
│ └── page.tsx # /user/:id 页面
└── error.tsx # 错误页面
每个 page.tsx
文件代表一个路由页面:
1// src/routes/page.tsx
2export default function HomePage() {
3 return (
4 <div>
5 <h1>欢迎使用 fs-router</h1>
6 <p>这是首页</p>
7 </div>
8 )
9}
通过文件夹嵌套创建嵌套路由:
1// src/routes/about/page.tsx
2export default function AboutPage() {
3 return (
4 <div>
5 <h1>关于我们</h1>
6 <p>这是关于页面</p>
7 </div>
8 )
9}
layout.tsx
文件定义页面布局:
1// src/routes/layout.tsx
2import { Outlet } from 'react-router-dom'
3
4export default function RootLayout() {
5 return (
6 <div className="app">
7 <header>
8 <nav>
9 <a href="/">首页</a>
10 <a href="/about">关于</a>
11 <a href="/user">用户</a>
12 </nav>
13 </header>
14 <main>
15 <Outlet />
16 </main>
17 <footer>
18 <p>© 2024 My App</p>
19 </footer>
20 </div>
21 )
22}
可以为特定路由段创建专门的布局:
1// src/routes/user/layout.tsx
2import { Outlet } from 'react-router-dom'
3
4export default function UserLayout() {
5 return (
6 <div className="user-layout">
7 <aside>
8 <nav>
9 <a href="/user">用户首页</a>
10 <a href="/user/profile">个人资料</a>
11 <a href="/user/settings">设置</a>
12 </nav>
13 </aside>
14 <div className="user-content">
15 <Outlet />
16 </div>
17 </div>
18 )
19}
使用方括号 []
创建动态路由:
1// src/routes/user/[id]/page.tsx
2import { useParams } from 'react-router-dom'
3
4export default function UserDetailPage() {
5 const { id } = useParams()
6
7 return (
8 <div>
9 <h1>用户详情</h1>
10 <p>用户 ID: {id}</p>
11 </div>
12 )
13}
创建 error.tsx
文件处理错误:
1// src/routes/error.tsx
2import { useRouteError } from 'react-router-dom'
3
4export default function ErrorPage() {
5 const error = useRouteError()
6
7 return (
8 <div className="error-page">
9 <h1>出错了!</h1>
10 <p>抱歉,发生了意外错误。</p>
11 <p>
12 <i>{error?.statusText || error?.message}</i>
13 </p>
14 </div>
15 )
16}
1import { Link } from 'react-router-dom'
2
3export default function Navigation() {
4 return (
5 <nav>
6 <Link to="/">首页</Link>
7 <Link to="/about">关于</Link>
8 <Link to="/user/123">用户详情</Link>
9 </nav>
10 )
11}
1import { useNavigate } from 'react-router-dom'
2
3export default function MyComponent() {
4 const navigate = useNavigate()
5
6 const handleClick = () => {
7 navigate('/about')
8 }
9
10 return (
11 <button onClick={handleClick}>
12 前往关于页面
13 </button>
14 )
15}
在 React-Router 的设计中 Loader 仅支持 DataRouter 数据路由。
1// src/routes/user/[id]/page.data.ts
2import { fetchUser } from '@/services/user.service.ts'
3
4export async function loader({ params }) {
5 const user = await fetchUser(params.id)
6 return { user }
7}
1// src/routes/user/[id]/page.tsx
2import { useLoaderData } from 'react-router-dom'
3import { loader } from './page.data'
4
5export default function UserDetailPage() {
6 const { user } = useLoaderData<typeof loader>()
7
8 return (
9 <div>
10 <h1>{user.name}</h1>
11 <p>{user.email}</p>
12 </div>
13 )
14}