
路由参数与嵌套路由
一、路由参数
1.1 路径参数
// 路由配置
import { Routes, Route } from 'react-router-dom';
function App() {
return (
<Routes>
<Route path="/user/:id" element={<UserProfile />} />
<Route path="/product/:category/:id" element={<ProductDetail />} />
</Routes>
);
}
// 组件中获取参数
import { useParams } from 'react-router-dom';
function UserProfile() {
const { id } = useParams();
return <div>用户 ID: {id}</div>;
}
function ProductDetail() {
const { category, id } = useParams();
return <div>分类: {category}, 产品ID: {id}</div>;
}
1.2 可选参数
// 使用 ? 表示可选参数
<Route path="/user/:id?" element={<UserProfile />} />
<Route path="/product/:category?/:id?" element={<ProductDetail />} />
1.3 查询参数
import { useSearchParams } from 'react-router-dom';
function SearchPage() {
const [searchParams, setSearchParams] = useSearchParams();
const query = searchParams.get('q') || '';
const page = parseInt(searchParams.get('page') || '1');
const sort = searchParams.get('sort') || 'desc';
const updateSearch = (newQuery) => {
setSearchParams({ q: newQuery, page: '1', sort });
};
const nextPage = () => {
setSearchParams({ q: query, page: String(page + 1), sort });
};
return (
<div>
<input value={query} onChange={(e) => updateSearch(e.target.value)} />
<p>当前页: {page}</p>
<button onClick={nextPage}>下一页</button>
</div>
);
}
1.4 使用 location.state
// 传递 state
import { Link, useNavigate } from 'react-router-dom';
// 方式1:Link 组件
<Link to="/user/1" state={{ fromHome: true, timestamp: Date.now() }}>
用户详情
</Link>
// 方式2:编程式导航
const navigate = useNavigate();
navigate('/user/1', {
state: { fromHome: true, data: { id: 1 } }
});
// 获取 state
import { useLocation } from 'react-router-dom';
function UserProfile() {
const location = useLocation();
const fromHome = location.state?.fromHome;
const data = location.state?.data;
return (
<div>
<p>来自首页: {String(fromHome)}</p>
<p>数据: {JSON.stringify(data)}</p>
</div>
);
}
二、嵌套路由
2.1 基础嵌套
import { Outlet } from 'react-router-dom';
// 布局组件
function Layout() {
return (
<div>
<header>网站头部</header>
<nav>
<Link to="/">首页</Link>
<Link to="/about">关于</Link>
<Link to="/contact">联系</Link>
</nav>
<main>
<Outlet /> {/* 子路由渲染位置 */}
</main>
<footer>网站底部</footer>
</div>
);
}
// 路由配置
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="about" element={<About />} />
<Route path="contact" element={<Contact />} />
</Route>
</Routes>
</BrowserRouter>
);
}
2.2 深层嵌套
function DashboardLayout() {
return (
<div>
<Sidebar />
<div className="content">
<Outlet />
</div>
</div>
);
}
function PostsLayout() {
return (
<div>
<PostNav />
<Outlet />
</div>
);
}
// 路由配置
<Routes>
<Route path="/dashboard" element={<DashboardLayout />}>
<Route index element={<Overview />} />
<Route path="profile" element={<Profile />} />
<Route path="settings" element={<Settings />} />
{/* 嵌套更深 */}
<Route path="posts" element={<PostsLayout />}>
<Route index element={<PostList />} />
<Route path=":id" element={<PostDetail />} />
<Route path="create" element={<CreatePost />} />
</Route>
</Route>
</Routes>
2.3 相对链接
// 在 DashboardLayout 组件中
import { Link, Outlet } from 'react-router-dom';
function DashboardLayout() {
return (
<div>
<nav>
<Link to=".">概览</Link> {/* 当前路径 */}
<Link to="profile">个人资料</Link> {/* /dashboard/profile */}
<Link to="settings">设置</Link> {/* /dashboard/settings */}
<Link to="../">返回首页</Link> {/* 上一级 */}
</nav>
<Outlet />
</div>
);
}
三、Outlet 高级用法
3.1 传递 Context
function Layout() {
const [user, setUser] = useState(null);
return (
<div>
<Header />
<Outlet context={{ user, setUser }} />
</div>
);
}
// 子组件获取 context
import { useOutletContext } from 'react-router-dom';
function Home() {
const { user, setUser } = useOutletContext();
return (
<div>
<p>当前用户: {user?.name || '未登录'}</p>
<button onClick={() => setUser({ name: '张三' })}>登录</button>
</div>
);
}
3.2 TypeScript 类型
interface OutletContext {
user: User | null;
setUser: (user: User | null) => void;
}
function Home() {
const { user, setUser } = useOutletContext<OutletContext>();
// …
}

