一、从“挂载”说起:React 应用的起点
在 React 中,整个应用的启动始于一次“挂载”操作:
// main.js部分
import { createRoot } from 'react-dom/client';
import App from './App';
createRoot(document.getElementById('root')).render(<App />);
document.getElementById('root'):找到 HTML 中的容器<div id="root"></div>createRoot(...).render(<App />):将根组件<App />渲染到该容器中- 这是 唯一需要你手动写的挂载代码,后续所有子组件(如
<Home />、<About />)均由 React 自动管理
✅ 核心思想:你只需挂载“最大的组件”,React 负责其余一切。
二、什么是前端路由?
🌐 传统多页应用(MPA)
- 每个页面是一个独立 HTML 文件
- 点击链接 → 浏览器向服务器请求新页面 → 整页刷新
🔁 单页应用(SPA) + 前端路由
- 整个应用只有一个 HTML 页面
- URL 变化时,不刷新页面,仅替换部分内容
- 通过 JavaScript 动态切换组件,实现“多页面”体验
💡 前端路由 = URL 与 UI 组件的映射关系
三、React Router:React 的官方路由方案
1. 安装
npm install react-router-dom
2. 核心组成(v6+)
| 组件 | 作用 |
|---|---|
<BrowserRouter> | 使用 HTML5 History API 管理 URL(推荐) |
<Routes> | 路由匹配总管,只渲染第一个匹配的 <Route> |
<Route> | 定义路径与组件的映射 |
<Link> | 声明式导航(替代 <a>,避免刷新) |
3. 基本使用结构
▶ main.js:挂载根组件
js
编辑
createRoot(document.getElementById('root')).render(<App />);
▶ App.jsx:配置路由上下文 + 导航栏
import { BrowserRouter as Router, Link } from 'react-router-dom';
import AppRouters from './router';
function App() {
return (
<Router>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
<AppRouters />
</Router>
);
}
export default App;
▶ router/index.jsx:定义路由规则
import { Routes, Route } from 'react-router-dom';
import Home from '../pages/Home';
import About from '../pages/About';
export default function AppRouters() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
);
}
四、两个关键子组件详细
📄 Home.jsx:动态数据加载示例
import { useState, useEffect } from 'react';
const Home = () => {
const [repos, setRepos] = useState([]);
useEffect(() => {
// 组件挂载后执行(类似 Vue 的 onMounted)
fetch('https://api.github.com/users/shunwuyu/repos')
.then(res => res.json())
.then(json => setRepos(json));
}, []); // 空依赖 = 仅挂载时执行一次
return (
<div>
<h1>Home</h1>
{repos.length ? (
<ul>
{repos.map(repo => (
<li key={repo.id}>
<a href={repo.html_url} target="_blank" rel="noreferrer">
{repo.name}
</a>
</li>
))}
</ul>
) : <p>加载中或无数据</p>}
</div>
);
};
export default Home;
📄 About.jsx:静态页面示例
jsx
编辑
const About = () => {
return (
<div>
<h1>About</h1>
<p>这是一个关于页面。</p>
</div>
);
};
export default About;
五、React Router vs Vue Router:对比分析
| 特性 | React Router (v6) | Vue Router (v4) |
|---|---|---|
| 安装 | npm install react-router-dom | npm install vue-router |
| 路由定义 | JSX 嵌套 <Route> | 配置对象 routes: [{ path, component }] |
| 导航组件 | <Link to="/path"> | <router-link to="/path"> |
| 出口组件 | <Routes> + <Route> | <router-view /> |
| 编程式导航 | useNavigate() Hook | router.push() 或 this.$router |
| 动态参数 | useParams() | $route.params 或 useRoute().params |
| 嵌套路由 | 在 <Route> 内部再写 <Route> | children 配置项 |
| 状态管理集成 | 与 Redux/Zustand 无关 | 与 Vuex/Pinia 无关 |
✅ 共同点:
- 都基于 HTML5 History API
- 支持 动态路由、嵌套路由、路由守卫(权限控制)
- 实现 无刷新 SPA 体验
⚠️ 主要差异:
- React Router 更“JSX 化” :路由即组件,用 JSX 描述结构
- Vue Router 更“配置化” :用 JavaScript 对象声明路由表
六、性能与最佳实践
🚀 性能优势
- 按需加载:配合
React.lazy+Suspense实现代码分割 - 精准更新:仅 re-render 匹配的路由组件,不影响其他区域
- 无刷新跳转:减少网络请求,提升用户体验
✅ 最佳实践
-
路由组件放在
pages/目录,便于管理 -
使用函数式更新:
setTodos(prev => prev.filter(...)) -
添加 404 页面:
<Route path="*" element={<NotFound />} /> -
避免在路由中直接写逻辑,保持组件纯净
七、面试小知识(高频考点)
❓ 1. React Router 中 BrowserRouter 和 HashRouter 有什么区别?
BrowserRouter:使用history.pushState(),URL 如/about,需后端支持(避免 404)HashRouter:使用 URL hash,如/#/about,无需后端配置,但 SEO 较差
✅ 生产环境优先用
BrowserRouter
❓ 2. 为什么不能直接用 <a href="/about">?
<a>会触发浏览器默认行为 → 整页刷新,破坏 SPA 体验<Link>是 React Router 提供的组件,拦截点击事件,仅更新 URL 和组件
❓ 3. useEffect 依赖数组为空 [] 表示什么?
- 表示该副作用仅在组件挂载时执行一次(类似 Vue 的
onMounted) - 常用于:发起 API 请求、绑定事件监听等
❓ 4. 路由组件和普通组件有什么区别?
- 路由组件:由
<Route element={<X />} />渲染,通常代表一个“页面” - 普通组件:作为 UI 片段被复用(如
<Button />、<Header />) - 路由组件可使用
useParams、useNavigate等路由 Hooks
八、总结
- 挂载是起点:只需
render(<App />)一次,React 自动管理子组件 - 路由是导航系统:实现 URL 与组件的映射,构建 SPA
- React Router vs Vue Router:理念相同,API 风格不同(JSX vs 配置)
- 性能关键:按需加载、精准更新、避免整页刷新
掌握路由,你就掌握了现代前端应用的“骨架”。下一步可深入:路由守卫(权限控制) 、懒加载优化、服务端渲染(SSR)集成。