一句话总结
- Hash 模式 :利用 URL 中
#后的内容变化实现前端路由,不触发页面刷新,兼容性好。 - History 模式 :基于 HTML5 的
history.pushState()和popstate事件,URL 更干净,但需要服务端配合。
一、Hash 模式(默认模式)
1. 基本形式
bash
https://example.com/#/user/profile
↑
hash 部分
2. 工作原理
- 核心机制 :监听
window.onhashchange事件。 - 当用户点击链接或调用
router.push()时,Vue Router 修改location.hash(如#/home→#/about)。 - 浏览器不会向服务器发起请求 ,因为
#及其后的内容不会发送给服务器。 - 页面 URL 改变但不刷新,前端根据新的 hash 值匹配路由并渲染对应组件。
3. 特点
| 优点 | 缺点 |
|---|---|
| ✅ 兼容性极好(IE8+ 支持) | ❌ URL 中带有 #,不够美观 |
| ✅ 无需服务端配置 | ❌ SEO 友好性略差(部分爬虫可能忽略 hash) |
| ✅ 天然避免 404 问题 | ❌ 不符合传统 URL 语义 |
4. 示例代码(Vue Router 配置)
arduino
const router = new VueRouter({
mode: 'hash', // 默认值,可省略
routes: [...]
});
二、History 模式(推荐用于现代项目)
1. 基本形式
arduino
https://example.com/user/profile
URL 看起来和传统多页应用一致,无 # 符号。
2. 工作原理
- 核心技术:
-
history.pushState(state, title, url):在不刷新页面的情况下修改浏览器历史记录和 URL。history.replaceState(...):替换当前历史记录。window.onpopstate:监听浏览器前进/后退操作(如点击 ← → 按钮)。
- 流程示例:
-
- 用户访问
/home→ 前端加载,Vue Router 渲染 Home 组件。 - 点击"关于"链接 → 调用
router.push('/about')→ 执行history.pushState(null, '', '/about')。 - URL 变为
https://example.com/about,页面不刷新,About 组件被渲染。 - 用户刷新页面 → 浏览器向服务器请求
/about资源。
- 用户访问
3. 关键问题:刷新 404
- 原因 :服务器收到
/about请求时,若未配置,会尝试查找物理路径下的about.html或目录,找不到则返回 404。 - 解决方案 :服务端需配置"兜底路由" ,将所有前端路由请求重定向到
index.html。
Nginx 配置示例:
bash
location / {
try_files $uri $uri/ /index.html;
}
4. 特点
| 优点 | 缺点 |
|---|---|
| ✅ URL 简洁美观,符合 REST 风格 | ❌ 需要服务端支持(部署配置) |
| ✅ 更好的 SEO(主流爬虫已支持) | ❌ 在纯静态托管(如 GitHub Pages)中需额外处理 |
| ✅ 用户体验更接近原生 Web | ❌ 旧浏览器(IE9 以下)不支持 |
5. 示例代码(Vue Router 配置)
ini
const router = new VueRouter({
mode: 'history',
routes: [...]
});
🔁 三、对比总结
| 特性 | Hash 模式 | History 模式 |
|---|---|---|
| URL 样式 | example.com/#/path |
example.com/path |
| 刷新是否 404 | ❌ 不会(# 后内容不发给服务器) | ✅ 会(需服务端配置兜底) |
| 浏览器兼容性 | IE8+ | IE10+(HTML5 History API) |
| 服务端要求 | 无 | 必须配置 fallback 到 index.html |
| SEO 友好性 | 一般 | 较好(现代爬虫支持) |
| 使用场景 | 快速原型、老旧环境、无服务端控制权 | 正式项目、追求用户体验、有运维支持 |
💡 最佳实践建议
- 开发阶段 :两种模式均可,推荐
history提前暴露部署问题。 - 生产部署:
-
- 若使用 Nginx/Apache/Caddy → 优先选
history+ 配置 fallback。
- 若使用 Nginx/Apache/Caddy → 优先选
- 无法控制服务端? → 用
hash模式最稳妥。
补充知识
- 为什么 hash 不发给服务器?
根据 HTTP 规范,URL 中#fragment部分仅用于客户端定位(如锚点),不会包含在 HTTP 请求中。 - History API 安全限制
pushState只能修改同源下的路径,不能跨域篡改 URL,保障了安全性。