导航
什么是路由?
想象你是一位探险家,在互联网的大陆上旅行。每个URL都是一个藏宝点,而 路由 就是你的地图和指南针,指引你找到正确的宝藏(页面内容)。没有路由,你就会在茫茫代码海洋中迷失方向!
在Web开发中,路由就像餐厅的点餐系统:
- 顾客(用户)点单(输入URL或点击链接)
- 服务员(路由系统)接收请求
- 厨房(服务器/前端组件)准备餐品(页面内容)
- 最终呈现给顾客(用户界面)
路由的前世今生
1. 早期后端路由:古老的驿站系统
早期的Web就像古代驿站,每个URL对应一个具体的物理文件:
请求: /about.html → 服务器返回: about.html文件
请求: /user.php?id=123 → 服务器执行PHP脚本生成HTML
这种模式下,每次导航都会导致 页面刷新 ,就像每次换景点都要重新买门票一样麻烦。
2. 前端路由:现代导航系统
随着SPA(单页应用)
的兴起,前端路由应运而生。它就像智能导航系统,无需更换整个页面,只需更新需要变化的部分:
- 无刷新体验 :就像高铁换乘,不用下车就能切换路线
- 状态保留 :页面切换时不会丢失表单输入等临时数据
- 更快的响应 :只需加载必要资源,而非整个页面
在下一篇文章我会详细讲讲SPA,带你领略路由的成长。看看它是如何实现无刷路由的。
React Router实战指南
让我们一起解密它的魔法!
核心组件解析
BrowserRouter:
路由的指挥中心
我们在APP.jsx
中导入我们主角————'react-router-dom'
。记得先把react-router-dom
依赖导入我们的项目
npm install react-router-dom
// App.jsx
import {
BrowserRouter as Router, // 前端路由的核心容器
Routes, // 路由设置容器
Route // 单条路由规则
} from 'react-router-dom';
<Router>
就像交通指挥中心,负责管理所有路由规则和URL变化的监听。
Routes & Route:
路径与组件的映射表
在APP.jsx
的return
中我们使用下面的组件
// APP.jsx
<Router>
<Routes>
<Route path='/' element={<Home />}/>
<Route path='/About' element={<About />}/>
<Route path='/user/:id' element={<UserProfile />}/>
</Routes>
</Router>
<Routes>
:路由规则的容器,类似机场的航班信息显示屏<Route>
:单条路由规则,path
是URL路径,element
是要渲染的组件:id
:动态参数,就像快递单号,可以匹配不同用户ID
useParams:
获取动态参数的魔法钩子
import { useParams } from 'react-router-dom';
const UserProfile = () => {
const { id } = useParams(); // 从URL中提取id参数
return <h1>UserProfile {id}</h1>;
}
这就像从快递单号中获取收件人信息,通过 useParams
可以轻松拿到URL中的动态参数。
创建我们的页面
- 我们在
src
目录下新建一个pages
文件夹,在pages
文件夹下新建Home
、About
、UserProfile
文件夹,此时的项目结构为:
├── src/
│ └── pages/
│ ├── Home/
│ │ └── index.jsx
│ ├── About/
│ │ └── index.jsx
│ ├── UserProfile/
│ │ └── index.jsx
2. 分别书写我们的页面组件
- Home
// Home index.jsx
// 页面级组件
const Home = () => {
return (
<>
<h1>首页</h1>
</>
)
}
export default Home
- About
// About index.jsx
const About = () => {
return (
<>
<h1>关于</h1>
</>
)
}
export default About
- UserProfile
// UserProfile index.jsx
import {
useEffect
} from 'react';
import { useParams } from'react-router-dom';
const UserProfile = () => {
const {id} = useParams();
return (
<>
<h1>UserProfile {id}</h1>
</>
)
}
export default UserProfile;
- 查看效果
可以看到我们在地址栏输入对应的URL可以到达对应的页面,不需要输入文件名.后缀的格式了。下一篇文章我会细谈hashchange
在实现无刷路由方面的贡献。
嵌套路由:路由中的套娃艺术
- 就像俄罗斯套娃一样,一层套一层:
我们在
APP.jsx
的return
中加入下面这段代码。
<Route path='/products' element={<Products />}>
{/* 二级路由 */}
<Route path=':productId' element={<ProductDetails />}/>
<Route path='new' element={<NewProduct />}/>
</Route>
- 在
src
目录下的pages
中新建一个名为Products
的文件夹,此时的项目结构如下:
├── src/
│ └── pages/
│ ├── Home/
│ │ └── index.jsx
│ ├── About/
│ │ └── index.jsx
│ ├── UserProfile/
│ │ └── index.jsx
│ ├── Products/
│ │ ├── index.jsx # 产品列表页面
│ │ ├── NewProduct.jsx # 新增产品页面
│ │ └── ProductDetails.jsx # 产品详情页面
3. Products
下的组件代码分别为
- index.jsx
// index.jsx
import {Outlet} from 'react-router-dom';
const Products = () => {
return (
<>
<h1>Products</h1>
{/* 二级路由的占位符 */}
<Outlet />
</>
)
}
export default Products
<Outlet>
是React Router提供的嵌套路由占位组件
,用于在父路由组件中预留位置,供子路由组件渲染。它类似于模板引擎中的插槽(slot)或Vue的<router-view>
。
- NewProduct.jsx
// NewProduct.jsx
const NewProduct = () => {
return (
<>
<h2>NewProduct</h2>
</>
)
}
export default NewProduct
- ProductDetails
import { useParams } from'react-router-dom';
const ProductDetails = () => {
const {productId} = useParams(); // 从路由参数中获取productId
console.log(productId);
return (
<>
<h2>ProductDetails{productId}</h2>
</>
)
}
export default ProductDetails
- 最终效果
可以看到在Products
组件中又渲染了其子组件ProductDetails123
或ProductDetails1
————后面是什么取决于你输入的id
这便是二级路由。
🎬 总结:路由的未来
从后端路由到前端路由,再到现在的React Router,路由系统一直在进化。它不仅是URL和页面的映射,更是用户体验的关键组成部分。
你的项目如果包含了路由的核心功能:基本路由、动态参数、嵌套路由。未来可以尝试添加路由动画、代码分割、权限控制等高级特性,让你的应用更加专业!
记住:好的路由设计就像一本好的旅行指南,让用户在你的应用中畅游无阻,尽情探索每一个精彩角落。跟着我贝爷的步伐,探索每一个前端小知识吧!