hash和history路由的区别
Category(分类): Vue Status: 已校订(Vue Router 3 历史写法 + Vue Router 4)
在了解路由模式前,先理解 SPA 与前端路由:客户端导航通常复用当前文档,只更新地址、应用状态和局部视图,而不重新加载整份页面。SPA 不等于“首次把全部页面组件一起下载”;Vue Router 可以用动态 import() 按路由懒加载,SSR/SSG 也可以为不同 URL 返回对应 HTML。
SPA 与前端路由
SPA 的优势通常包括流畅的站内导航、清晰的前后端职责和较强交互能力;代价则可能包括首屏 JavaScript 成本、部署回退配置,以及纯客户端渲染时的 SEO 风险。这些是架构取舍,不是每个 SPA 必然具有的结果。
前端路由的核心是:改变当前应用视图与可导航 URL,而不在每次站内切换时重新请求整份文档。

Vue Router 的版本差异
Vue Router 3(常见于 Vue 2)历史写法:
const router = new VueRouter({
mode: 'history', // 省略时旧版默认使用 hash
routes,
})
Vue Router 4(Vue 3)已用必填的 history 选项取代 mode:
import {
createRouter,
createWebHashHistory,
createWebHistory,
} from 'vue-router'
const historyRouter = createRouter({
history: createWebHistory('/'),
routes,
})
const hashRouter = createRouter({
history: createWebHashHistory('/'),
routes,
})
SSR 服务端通常使用 createMemoryHistory()。在 Nuxt 中路由由框架生成,一般不需要照抄上述初始化代码。
Hash 模式
原理
Hash 路由把客户端路径放在 fragment 中,例如:
https://example.com/#/articles/1
#/articles/1 是完整 URL 的一部分,但 fragment 不会随 HTTP 请求发送到服务器。浏览器可以通过 hashchange 监听变化,路由器再渲染对应组件。只改变 fragment 通常不会重新请求 HTML。

需要区分两种用途:
https://example.com/docs#install:普通文档内锚点,完全合法;https://example.com/#/products:用 fragment 表达不同应用页面,即 Hash 路由。
特点
- 地址中通常包含
#; - fragment 改变了完整 URL 和历史位置,但服务器看到的 path/query 不变;
- 无需服务器为深层前端路由配置 HTML fallback;
- 适合无法控制服务器回退的静态托管、内部工具或无需收录的页面;
- 不宜用来表示希望独立索引的公开页面。Google 建议用真实 path 和 History API 表达不同内容页面。
“每次设置 hash 都必然增加历史记录”并不严谨:是否新增条目取决于实际值和所用 API;例如 location.replace() 可替换当前记录。
History 模式
原理
History 模式使用 history.pushState()、history.replaceState() 和 popstate 等能力,让 URL 呈现为普通路径:
https://example.com/articles/1
history.pushState({ from: 'home' }, '', '/articles/1')
history.replaceState({ from: 'list' }, '', '/articles/1')
pushState() 新增会话历史条目,replaceState() 替换当前条目;两者本身都不会立即加载新 URL,也不会立即发出 HTTP 请求。用户刷新、直接输入 URL、从外站进入或进行普通文档导航时,浏览器才会向服务器请求该 path。

重要限制
- 新 URL 必须与当前页面同源;
- state 必须可序列化,浏览器还可能限制其大小,不能笼统说可放“任意类型”;
- 第二个参数是历史遗留的 unused 参数,通常传空字符串;多数浏览器忽略它,不能把它当作页面 title;
- Vue Router 会在
history.state中保存导航和滚动信息,业务代码不应随意整体覆盖; popstate主要在用户前进/后退等激活历史条目时触发,调用pushState()本身不会触发popstate。
当前 Vue Router 4 面向的浏览器都支持 HTML5 History API。“低版本浏览器兼容性差”只适合历史项目背景,不再是现代 Vue 3 项目的主要判断依据。
为什么刷新深层 URL 可能 404
站内调用 pushState() 时没有请求服务器,所以切换正常。但若在 /articles/1 刷新,服务器会收到这个 path。服务器若只存在根目录 index.html,就可能返回 404。
Hash 模式刷新时,fragment 不会发送给服务器,服务器仍只收到 /,因此通常不需要路由 fallback。准确说法不是“hash 没改变 URL”,而是“hash 改变了完整 URL,但没有改变发送给服务器的 path/query”。
开发环境是否自动回退取决于 Vite、Vue CLI、Nuxt 或具体 dev server 的配置,不能笼统归因于 webpack。

History 模式的服务器 fallback
静态 History SPA 的概念配置如下:
# API 不能被 SPA 入口吞掉
location /api/ {
proxy_pass http://backend;
}
# 构建资产不存在时应返回真实 404
location /assets/ {
try_files $uri =404;
}
# 仅应用页面回退到入口 HTML
location / {
try_files $uri $uri/ /index.html;
}

这里不是要求“前端 URL 与后端接口 URL 完全一致”,而是要求服务器知道哪些路径属于前端应用,并为它们返回入口 HTML。还应注意:
- API、静态资源、
robots.txt、sitemap.xml等应优先匹配; - 部署到
/app/等子目录时,服务器入口、资源 base 与createWebHistory('/app/')必须一致; - catch-all 会让服务器难以自动返回页面级 404。未知路由应由服务端正确返回 404,或至少让客户端错误页
noindex,避免 soft 404; - Nuxt/Nitro SSR 不是把所有请求改写到静态
index.html,而是把请求交给 Nitro,让服务端路由返回 HTML 和正确状态码。
Hash 与 History 对照
| 维度 | Hash | History |
|---|---|---|
| 示例 | /#/articles/1 | /articles/1 |
| 服务器收到客户端路由 | 否,fragment 不发送 | 首次直达/刷新时会收到 path |
| 站内切换是否立即请求 HTML | 通常否 | pushState 本身也不会 |
| 部署要求 | 通常无需 fallback | 深层路由需 fallback 或 SSR 路由 |
| 公开页面 SEO | 不建议用 fragment 表达不同页面 | 更适合规范、独立的页面 URL |
| 常见场景 | 内部工具、受限静态托管 | 可配置服务器的现代 Web 应用 |
结论
- Vue Router 3 的
mode是 Vue 2 历史写法;Vue Router 4 使用createWebHashHistory()或createWebHistory()。 - Hash fragment 是 URL 的一部分,但不会发送到服务器。
pushState()改地址和历史记录,却不会自行发请求;History 深层 URL 在刷新/直达时需要服务器处理。- History fallback 不能吞掉 API、资产与真实 404。
- SEO 结论要有边界:普通
#section锚点没有问题;不推荐的是用#/route表达不同的可索引页面。
原文参考 / 延伸阅读
以下保留原作者各段引用与推荐阅读。它们是社区历史资料,部分链接可能已失效或内容已过时;涉及版本与部署结论时,应再与下方官方文档核对。
- Vue 前端路由工作原理,hash 与 history 之间的区别
- 在 SPA 项目的路由中,注意 hash 与 history 的区别
- 深入了解前端路由 hash 与 history 差异(原文微信链接)
- 前端框架路由实现的 Hash 和 History 两种模式的区别
- Vue 了解前端路由 hash 与 history 差异
- 推荐:面试被问及 hash 与 history 的区别该怎么回答?
- 原作者注明的同小颖博客:hash 和 history 路由的区别
官方参考
- Vue Router 4:不同 History 模式
- Vue Router 4:从 Vue 2 迁移
- Vue Router:路由懒加载
- MDN:URI fragment
- MDN:History.pushState
- MDN:popstate
- Google:JavaScript SEO 基础
作者:前端程序媛_西安 原文链接:https://juejin.cn/post/7116336664540086286 来源:稀土掘金。著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。