单页面应用(SPA)的精髓在于「不刷新页面却能无缝切换内容」,而 react-router-dom 就是实现这一魔法的核心工具。除了基础的路由配置,它还有不少进阶玩法能让你的应用更高效、更安全。今天咱们就掰开揉碎了讲,带代码、带原理,保证看完就会用!😉
一、路由懒加载:让首屏加载飞起来 ⚡
想象一下:如果你的应用有 30 多个页面,首屏加载时就把所有组件都打包进来,用户怕是要等到地老天荒… 😫 路由懒加载就是来解决这个问题的 ——只加载当前页面需要的组件,其他组件等用到再说!
👉 实现方式:lazy + Suspense 组合拳
看看 App.jsx 里的代码:
// 传统导入:一次性加载所有组件(坑!)
// import Home from './pages/Home'
// import About from './pages/About'
// 进阶操作:懒加载!
import { lazy, Suspense } from 'react'
const Home = lazy(() => import('./pages/Home'))
const About = lazy(() => import('./pages/About'))
const NotFound = lazy(() => import('./pages/NotFound'))
-
lazy函数:接收一个动态导入函数(() => import('./pages/Home')),返回一个「待加载」的组件。只有当路由匹配时,才会真正请求这个组件的代码。 -
Suspense组件:懒加载时组件不会瞬间加载完成,这时候就需要一个「加载中」的占位符(比如 spinner 动画)。fallback属性就是干这个的:<Suspense fallback={ <div> <img src="https://static.360buyimg.com/item/main/1.0.12/css/i/loading.gif" alt="加载中" /> </div> }> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> </Routes> </Suspense>
🧠 原理揭秘:
- 传统
import会在打包时把所有组件塞进一个 JS 文件,体积超大。 - 动态
import()会把每个组件拆成单独的「代码块」,只有路由被访问时才会加载对应的代码块,首屏加载体积直接砍半!
二、路由鉴权:保护敏感页面不被乱闯 🔒
有些页面(比如支付页 /pay)可不是谁都能进的,必须登录后才能访问。这时候就需要「路由鉴权」—— 像保安一样守住入口,没权限?对不起,请先登录!🚫
👉 实现方式:自定义 ProtectRoute 组件
ProtectRoute 组件堪称典范,咱们拆解一下:
import { Navigate, useLocation } from 'react-router-dom'
const ProtectRoute = (props) => {
const { children } = props // 要保护的子组件(比如 <Pay />)
const { pathname } = useLocation() // 获取当前访问的路径
const isLogin = localStorage.getItem('isLogin') === 'true' // 登录状态判断
if (!isLogin) {
// 未登录?重定向到登录页,顺便记下从哪来的
return <Navigate to="/login" state={{ from: pathname }} />
}
return children // 已登录?直接显示子组件
}
怎么用?像「套娃」一样包裹需要保护的路由:
<Route path="/pay" element={
<ProtectRoute>
<Pay /> {/* 只有登录后才能看到这个组件 */}
</ProtectRoute>
}/>
🧠 核心逻辑:
- 用
localStorage存储登录状态(实际项目可能用redux或context)。 - 未登录时,通过
Navigate组件重定向到登录页(302 临时重定向)。 - 关键细节:用
state={{ from: pathname }}记录用户原本想访问的路径,登录后能直接跳回去,体验更丝滑~
三、登录页:不仅要登录,还要「记住来时的路」🔑
登录页不是孤立的 —— 用户可能从「支付页」被踢过来,也可能从「个人中心」被踢过来。登录成功后,得让他们回到原来的页面,而不是一刀切跳首页。
👉 登录页的「智能跳转」实现:
看看 Login.jsx 的代码:
import { useState } from 'react'
import { useNavigate, useLocation } from 'react-router-dom'
const Login = () => {
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
const location = useLocation() // 获取路由状态
const navigate = useNavigate() // 编程式导航工具
const handleSubmit = (e) => {
e.preventDefault()
// 简单验证:用户名 admin + 密码 123456
if (username === 'admin' && password === '123456') {
localStorage.setItem('isLogin', 'true') // 标记已登录
// 跳回之前的页面(如果有),否则去首页
navigate(location?.state?.from || '/')
} else {
alert('账号密码错啦!')
}
}
return (
<form onSubmit={handleSubmit}>
<h1>登录页面</h1>
<input type="text" value={username} onChange={(e) => setUsername(e.target.value)} />
<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} />
<button type="submit">登录</button>
</form>
)
}
🧠 关键技巧:
useNavigate:替代传统的history.push,让你在 JS 里自由跳转路由。location.state.from:接收ProtectRoute传过来的「来源路径」,登录后精准跳转,用户体验拉满!
四、导航组件:用 Link 替代 a 标签的秘密 🧭
你可能会问:导航链接用 <a href="/about"> 不行吗?还真不行!传统 a 标签会触发页面刷新,打破 SPA 的「无刷新体验」。react-router-dom 提供的 Link 组件才是正道:
import { Link } from 'react-router-dom'
const Navigation = () => {
return (
<nav>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
</ul>
</nav>
)
}
🧠 为什么 Link 更好?
- 它会阻止浏览器默认的跳转行为(不会刷新页面)。
- 只更新 URL 和对应的组件,页面其他部分保持不变,性能更好。
- 自动给当前激活的链接添加
active类名,方便做样式高亮(进阶可以用NavLink)。
五、404 页面:给「迷路」的用户一个交代 🚫
用户手滑输错 URL 怎么办?总不能显示一片空白吧?用 path="*" 匹配所有未定义的路由,指向 404 组件:
// App.jsx 中最后一个 Route
<Route path="*" element={<NotFound />} />
// NotFound.jsx
const NotFound = () => {
return <div><h1>404 Not Found</h1></div>
}
🧠 小技巧:
path="*"必须放在所有路由的最后,因为路由匹配是「从上到下」的,前面的路由没匹配上,才会走这个兜底规则。- 可以在 404 页面加个「返回首页」的
Link,引导用户回到正轨~
六、总结:进阶功能的核心价值 🌟
| 功能 | 解决的问题 | 核心工具 |
|---|---|---|
| 路由懒加载 | 首屏加载慢、资源浪费 | lazy + Suspense |
| 路由鉴权 | 未登录用户访问敏感页面 | ProtectRoute + Navigate |
| 智能登录跳转 | 登录后不知道回哪去 | useLocation + useNavigate |
| 导航组件 | 避免页面刷新,保持 SPA 体验 | Link |
| 404 处理 | 无效 URL 导致的空白页面 | path="*" |
这些功能看似零散,实则环环相扣 —— 从性能优化到安全防护,再到用户体验,都是企业级应用的必备技能。下次开发 React 项目时,不妨试试这些技巧,让你的应用既轻快又靠谱!💪
如果觉得有用,别忘了点赞收藏,下次遇到路由问题直接翻出来抄作业~ 😏