路由
路由的本质是把 URL 映射到资源、页面或处理逻辑;在前端里,它也是把 URL 组织成应用状态和页面结构的基础。
[!info] related notes
- 所属 MOC: 前端基础 MOC
- 浏览器上下文: browser, 浏览器导航与前端路由, History 对象
- 框架落地: Vue Router
- 相关主题: SPA vs MPA, 页面运行时状态
路由
路由的本质是:当 URL 变化时,系统应当展示什么内容、执行什么逻辑。
一句话定义
路由就是 URL 到资源、页面、组件或处理逻辑的映射规则。
先区分两层含义
浏览器层
- URL 如何解析
- 导航是否触发网络请求
- 历史记录如何入栈和回退
应用层
- URL 变化后渲染哪个视图
- 参数如何解析
- 是否要重定向、鉴权、懒加载、拉数据
前端常说的“路由”,通常是浏览器能力和应用级页面系统叠在一起后的统称。
URL 里最关键的三部分
以这个地址为例:
https://example.com:8080/user/profile?id=123#section1
前端路由最关心的是:
path:/user/profilequery:?id=123hash:#section1
path
表示页面路径或资源层级。
query
适合表示筛选、搜索、分页、排序等附加条件。
hash
最初用于页面内锚点跳转;它不会被发送给服务器,后来也被前端框架拿来做 Hash 路由。
为什么路由不只是“跳页面”
在现代前端里,路由通常还承担这些职责:
- 表达页面结构
- 把一部分状态编码进 URL
- 让刷新、分享、前进后退可用
- 作为守卫、懒加载、数据获取的骨架
所以路由不仅是“从 A 去 B”,也是“如何把 URL 变成应用状态”。
前端里的两种核心实现方式
Hash 路由
URL 形如:
/#/home
/#/about
核心点:
#后面的内容不会发给服务器- 修改 hash 不会触发整页刷新
- 浏览器可通过
hashchange事件监听变化
window.addEventListener('hashchange', () => {
console.log(location.hash)
})
优点:
- 实现简单
- 不依赖服务端回退配置
- 老环境里兼容性更稳
缺点:
- URL 不够自然
- 语义上不像真实路径
- 某些 SEO 场景不如 History 路由
History 路由
URL 形如:
/home
/about
核心依赖 HTML5 History API:
history.pushState()history.replaceState()popstate
history.pushState({ page: 'home' }, '', '/home')
window.addEventListener('popstate', () => {
console.log(location.pathname)
})
优点:
- URL 更自然
- 更符合现代 Web 应用习惯
- 更适合和 SSR / 服务端路由协作
缺点:
- 部署时需要服务端配合
- 直接访问或刷新子路径时,若服务器没有回退到
index.html,就会 404
Hash 和 History 怎么选
如果优先考虑部署简单性,Hash 更省事。
如果优先考虑 URL 规范性和现代工程实践,History 更常见。
最短记忆:
- Hash:简单、稳、带
# - History:自然、现代、需要服务端回退
SPA 和路由的关系
单页面应用不等于没有页面,而是物理上通常只有一个 HTML,逻辑上仍然有很多页面视图。
这些逻辑页面就是靠路由系统切换出来的。
所以可以把前端路由理解成:SPA 的页面系统。
和导航的关系
- 导航更偏“URL 如何变化,以及浏览器接下来做什么”
- 路由更偏“这个 URL 该映射到什么内容或逻辑”
两者在浏览器里彼此耦合,但不是同一个词。
常见误解
不是只有后端才有路由
后端路由通常把 URL 映射到控制器、接口或资源;前端路由则把 URL 映射到页面组件或页面状态。
不是“有 AJAX 就不需要路由”
即使页面内容能异步拉取,路由仍然负责:
- 刷新恢复
- 页面可分享
- 历史记录同步
- 页面层级组织
路由不只是跳转工具
它还是应用状态和页面结构的表达方式。
和框架的关系
浏览器只提供底层能力,例如 hash、History API、前进后退记录。
像 Vue Router 这样的库,才是在这些底层能力上封装出组件映射、守卫、嵌套、懒加载等工程能力。
如果要看浏览器导航、会话历史、pushState()、服务端 fallback 与 SPA 接管之间的完整关系,继续看:
最短记忆方式
路由 = URL 到内容的映射规则。
前端路由 = 在不整页刷新的前提下,让 URL 仍然表达页面状态与页面结构。