导语:未拆封的信笺躺在抽屉深处,如同未被唤起的往事——直到某天风吹动门扉,那些字句突然开始呼吸。技术亦是如此,从一个
Hello World
开始,构建你的全栈世界。
本文将带你使用 Vite + React + TypeScript 作为技术栈,从零开始学习 react-router-dom
,并通过构建一个名为“小时站”的精炼项目来实践所学知识。
一、环境准备
1. 使用 Vite 创建 React-TS 项目
打开终端,执行以下命令:
# 创建项目
npm create vite@latest hour-station -- --template react-ts
# 进入项目
cd hour-station
# 安装依赖
npm install
# 安装路由库
npm install react-router-dom @types/react-router-dom
# 启动开发服务器
npm run dev
2. 初始化项目结构
创建以下目录和文件:
src/
├── pages/
│ ├── Home.tsx
│ ├── About.tsx
│ ├── Contact.tsx
│ └── User.tsx
├── App.tsx
├── main.tsx
└── vite-env.d.ts
二、基础路由实现
1. 修改 App.tsx
这是应用的主组件,负责定义路由导航和路由出口。
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Contact from './pages/Contact';
function App() {
return (
<Router>
<nav style={{ padding: '10px', background: '#f0f0f0' }}>
<Link style={{ margin: '0 10px' }} to="/">首页</Link>
<Link style={{ margin: '0 10px' }} to="/about">关于</Link>
<Link style={{ margin: '0 10px' }} to="/contact">联系</Link>
</nav>
<div style={{ padding: '20px' }}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</div>
</Router>
);
}
export default App;
核心概念:
BrowserRouter
:提供基于 HTML5 History API 的路由。Routes
:包含所有Route
的容器。Route
:定义路径(path
)与对应组件(element
)的映射。Link
:用于导航的声明式组件,避免页面刷新。
React 的核心思想是组件化,它把 UI 看作是由一个或多个组件组合而成。App.tsx
、Home.tsx
、About.tsx
都是独立的组件。
2. 创建页面组件 (TypeScript 版)
pages/Home.tsx
export default function Home() {
return (
<div>
<h1>欢迎来到小时站</h1>
<p>这是一个使用 Vite + React + TypeScript 构建的示例项目</p>
</div>
);
}
关于 TSX:
JSX
是 JavaScript 的语法扩展,允许在 JS 中编写类似 HTML 的标记,用于描述 UI 结构。TSX
是JSX
的 TypeScript 版本,在 JSX 基础上增加了静态类型检查,适用于 TypeScript 项目。
pages/About.tsx
export default function About() {
return <h1>关于我们</h1>;
}
pages/Contact.tsx
export default function Contact() {
return <h1>联系我们</h1>;
}
三、进阶功能实现
1. 动态路由
实现 /user/123
、/user/456
等路径,其中 123
、456
是动态的用户 ID。
pages/User.tsx
import { useParams } from 'react-router-dom';
interface UserParams {
id: string;
}
export default function User() {
const { id } = useParams<UserParams>();
return <h1>用户ID: {id}</h1>;
}
更新 App.tsx
路由配置
import User from './pages/User';
// 在 <Routes> 中添加
<Route path="/user/:id" element={<User />} />
:id
是一个路由参数,可以通过useParams()
Hook 获取。
2. 嵌套路由 (TypeScript 版)
在“关于”页面下,创建“团队”和“历史”两个子页面。
重构 pages/About.tsx
import { Routes, Route, Link, Outlet } from 'react-router-dom';
export default function About() {
return (
<div>
<h1>关于我们</h1>
<nav style={{ margin: '10px 0' }}>
<Link style={{ margin: '0 10px' }} to="team">团队</Link>
<Link style={{ margin: '0 10px' }} to="history">历史</Link>
</nav>
<Outlet /> {/* 子路由组件的渲染位置 */}
</div>
);
}
// 导出子组件
export function Team() {
return <h2>我们的团队</h2>;
}
export function History() {
return <h2>发展历史</h2>;
}
更新 App.tsx
import About, { Team, History } from './pages/About';
// 修改 About 路由,添加子路由
<Route path="/about" element={<About />}>
<Route path="team" element={<Team />} />
<Route path="history" element={<History />} />
</Route>
Outlet
组件是父路由中用于渲染其子路由的占位符。
四、完整“小时站”实现
1. 完整 App.tsx
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import Home from './pages/Home';
import About, { Team, History } from './pages/About';
import Contact from './pages/Contact';
import User from './pages/User';
function App() {
return (
<Router>
<nav
style={{
padding: '10px',
background: '#f0f0f0',
display: 'flex',
gap: '10px'
}}
>
<Link to="/">首页</Link>
<Link to="/about">关于</Link>
<Link to="/contact">联系</Link>
<Link to="/user/123">示例用户</Link>
</nav>
<div style={{ padding: '20px' }}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />}>
<Route path="team" element={<Team />} />
<Route path="history" element={<History />} />
</Route>
<Route path="/contact" element={<Contact />} />
<Route path="/user/:id" element={<User />} />
</Routes>
</div>
</Router>
);
}
export default App;
2. 增强版 Home.tsx
(带 TypeScript 类型)
import { Link } from 'react-router-dom';
interface UserLink {
id: string;
name: string;
}
export default function Home() {
const users: UserLink[] = [
{ id: '1', name: '用户一' },
{ id: '2', name: '用户二' },
{ id: '3', name: '用户三' }
];
return (
<div>
<h1>欢迎来到小时站</h1>
<p>这是一个使用 Vite + React + TypeScript 构建的示例项目</p>
<div style={{ marginTop: '20px' }}>
<h3>热门用户</h3>
<ul style={{ listStyle: 'none', padding: 0 }}>
{users.map(user => (
<li key={user.id} style={{ margin: '5px 0' }}>
<Link to={`/user/${user.id}`}>{user.name}</Link>
</li>
))}
</ul>
</div>
</div>
);
}
五、TypeScript 进阶技巧
1. 自定义路由类型
创建 types/router.d.ts
文件,定义可复用的类型。
import { ReactNode } from 'react';
export interface RouteItem {
path: string;
element: ReactNode;
children?: RouteItem[];
}
export interface UserParams {
id: string;
}
2. 使用 useNavigate
进行编程式导航
import { useNavigate } from 'react-router-dom';
function UserActions() {
const navigate = useNavigate();
const handleClick = (userId: string) => {
navigate(`/user/${userId}`);
};
return (
<button onClick={() => handleClick('123')}>
查看用户
</button>
);
}
总结
恭喜!你已经成功构建了一个功能完整的 React 应用。
通过本次实践,你掌握了:
- ✅ 使用 Vite 快速搭建 React + TypeScript 开发环境
- ✅
react-router-dom
的核心概念:BrowserRouter
、Routes
、Route
、Link
、Outlet
- ✅ 动态路由 (
:id
) 与嵌套路由的实现 - ✅ 在 TypeScript 中为路由参数和组件定义类型