本节摘要:单页应用的"翻页"靠路由:地址与视图一一对应,切换用地址驱动而不重载页面。前端路由的原理(按路径匹配组件)与 React Router / Vue Router 的实践,本节一起讲清。你会明白为什么路由是单页应用骨架的一部分。
本节阅读目标
阅读完本节,你应当能够:
没有路由的单页,切页靠手改组件状态、不体现在地址上,无法收藏也无法分享。路由把这件事绑定到地址:访问某个路径,就渲染对应的视图组件;点击链接切换路径,不重载页面,只换上新的组件树。这就是"地址(URL)驱动界面"。
开发体验上后者更干净,但部署时要记得配好"任何路径都回退到入口"的规则,否则刷新会 404。
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom'; function App() { return ( <BrowserRouter> <nav> <Link to="/">首页</Link> <Link to="/about">关于</Link> </nav> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> <Route path="/user/:id" element={<User />} /> </Routes> </BrowserRouter> ); }
Routes/Route 声明路径与视图的映射,:id 表示路径参数。import { createRouter, createWebHistory } from 'vue-router'; import Home from './views/Home.vue'; import About from './views/About.vue'; const routes = [ { path: '/', component: Home }, { path: '/about', component: About }, ]; export default createRouter({ history: createWebHistory(), routes });
在根组件里挂一个路由视图占位,模板里用 router-link 做导航、router-view 显示当前视图。概念与 React Router 一一对应:路径表、链接、视图占位。
带参数的页面最考验路由手感。React 侧在 Route 里声明 path="/user/:id",组件里用一个钩子取到 id:
import { useParams } from 'react-router-dom'; function User() { const { id } = useParams(); // 从路径读到 :id 的值 return <p>用户 {id}</p>; }
Vue 侧在 routes 表里写 path: '/user/:id',组件用组合式 API 取参:
<script setup> import { useRoute } from 'vue-router'; const route = useRoute(); // route.params.id 即路径参数 </script> <template><p>用户 {{ route.params.id }}</p></template>
注意两条取参路径的各自边界:React 用 useParams 是用来读"路径段",读查询串要另用 useSearchParams;Vue 里 route.params 管路径参数、route.query 管 ?a=1 那类查询。分清"路径参数"和"查询参数"两种来源,排查"为什么取到的 id 是 undefined"时就不至于在两条通道里瞎找——多半是把 Query 当 Param 用了。

路由导航不止到 <Link> / <RouterLink> 为止,业务里还有很多"动作后跳转"的场景——提交完表单回到列表、权限不足去登录页。这些都要在 JavaScript 代码里触发跳转,而不是靠用户点链接。React 用导航钩子拿到一个跳转函数,Vue 的 setup 里则用路由实例的 push:
// React const navigate = useNavigate(); function afterSubmit() { navigate('/done'); } // 提交后跳走
// Vue(组合式 API) import { useRouter } from 'vue-router'; const router = useRouter(); function afterSubmit() { router.push('/done'); }
这一对写法与 <Link> / <RouterLink> 各管一类:声明式链接适合"页面内固定的导航入口",命令式跳转适合"动作触发的去向"。把两者区分开,代码意图更清楚——该让用户点哪走哪的用链接,该由程序决定去向的用编程式跳转。顺带一提跳转同样可以带参数(push('/user/' + id)),复用前面讲的参数取读。
页面能切换了,最后一块是数据——组件跟后端取数。下一节异步数据请求管理,把 loading、成功、失败三态编排清楚。