Vue.js 源码分析:history 与 hash 模式实现差异
【免费下载链接】vue-analysis :thumbsup: Vue.js 源码分析 项目地址: https://gitcode.com/gh_mirrors/vu/vue-analysis
在构建单页应用(SPA)时,前端路由是核心功能之一。Vue.js 生态中的 vue-router 提供了两种主要路由模式:Hash 模式和 History 模式。本文将从源码角度深入分析这两种模式的实现差异,帮助开发者理解其工作原理及适用场景。
路由模式基础架构
vue-router 的路由系统基于 History 基类构建,两种模式通过继承该基类实现特定功能。基类定义了路由的核心逻辑,包括路由过渡、守卫处理和 URL 同步等基础功能。
History 基类核心实现:
- vue-router/src/history/base.js 定义了路由的基础框架,包含
transitionTo方法处理路由切换、confirmTransition方法管理导航守卫队列,以及updateRoute方法更新当前路由状态。 - 基类通过
listen方法注册回调,在路由变化时通知应用更新视图。
// 路由过渡核心逻辑
transitionTo (location: RawLocation, onComplete?: Function, onAbort?: Function) {
const route = this.router.match(location, this.current)
this.confirmTransition(route, () => {
this.updateRoute(route)
onComplete && onComplete(route)
this.ensureURL() // 同步 URL
}, err => {
onAbort && onAbort(err)
})
}
Hash 模式实现原理
Hash 模式利用 URL 中的哈希(#)部分实现路由,哈希值的变化不会触发页面刷新,但会在浏览器历史记录中添加条目。
核心实现文件
- vue-router/src/history/hash.js 实现了 HashHistory 类,继承自 History 基类。
关键技术点
- URL 哈希管理
- 通过
getHash方法获取当前哈希值,避免直接使用window.location.hash以解决浏览器兼容性问题。 pushHash和replaceHash方法通过修改哈希值实现路由切换,支持浏览器前进/后退导航。
- 通过
// 获取哈希值(兼容 Firefox 预解码问题)
export function getHash (): string {
const href = window.location.href
const index = href.indexOf('#')
return index === -1 ? '' : href.slice(index + 1)
}
-
事件监听
- 监听
hashchange事件(或popstate事件,取决于浏览器是否支持pushState),在哈希变化时触发路由过渡。 setupListeners方法中注册事件处理器,确保哈希值以斜杠开头,维持路由路径格式一致性。
- 监听
-
回退兼容性
- 当浏览器不支持
pushState时,通过replaceHash方法同步 URL,确保路由状态正确。
- 当浏览器不支持
History 模式实现原理
History 模式利用 HTML5 History API(pushState、replaceState)实现路由,URL 路径与传统网站一致,不包含哈希符号,但需要服务器配置支持。
核心实现文件
- vue-router/src/history/html5.js 实现了 HTML5History 类,继承自 History 基类。
关键技术点
- History API 应用
- 使用
pushState和replaceState方法修改浏览器历史记录,实现无刷新 URL 更新。 getLocation方法从window.location.pathname提取路径,结合 base 路径处理路由匹配。
- 使用
// 推送新路由状态
push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
const { current: fromRoute } = this
this.transitionTo(location, route => {
pushState(cleanPath(this.base + route.fullPath)) // 使用 HTML5 API
handleScroll(this.router, route, fromRoute, false)
onComplete && onComplete(route)
}, onAbort)
}
-
事件监听
- 监听
popstate事件响应浏览器前进/后退操作,触发路由过渡。 - 通过
initLocation变量避免初始加载时的冗余路由处理。
- 监听
-
服务器配置依赖
- 需服务器将所有路由请求重定向到应用入口页面(如
index.html),否则刷新页面会导致 404 错误。
- 需服务器将所有路由请求重定向到应用入口页面(如
两种模式核心差异对比
| 特性 | Hash 模式 | History 模式 |
|---|---|---|
| URL 格式 | http://example.com/#/path | http://example.com/path |
| 浏览器支持 | 所有现代浏览器 | IE10+ |
| 服务器配置 | 无需特殊配置 | 需要配置 fallback 页面 |
| 历史记录 | 通过修改哈希实现 | 使用 HTML5 History API |
| 路径长度限制 | 受浏览器对 URL 长度限制 | 理论无限制 |
| SEO 友好性 | 较差(部分搜索引擎忽略哈希) | 较好 |
关键实现差异代码对比
URL 同步机制:
// Hash 模式:通过修改哈希值同步 URL
ensureURL (push?: boolean) {
const current = this.current.fullPath
if (getHash() !== current) {
push ? pushHash(current) : replaceHash(current)
}
}
// History 模式:通过 History API 同步 URL
ensureURL (push?: boolean) {
if (getLocation(this.base) !== this.current.fullPath) {
const current = cleanPath(this.base + this.current.fullPath)
push ? pushState(current) : replaceState(current)
}
}
模式选择与应用场景
Hash 模式适用场景
- 快速原型开发,无需服务器配置
- 兼容旧版浏览器(如 IE9 及以下)
- 静态站点部署(如 GitHub Pages)
History 模式适用场景
- 追求 URL 美观性和 SEO 优化
- 复杂单页应用,需要与后端 API 路由共存
- 对用户体验有较高要求的产品
源码中的浏览器兼容性处理
vue-router 在实现中充分考虑了浏览器兼容性,通过特性检测决定使用的 API:
// 事件监听兼容性处理
window.addEventListener(supportsPushState ? 'popstate' : 'hashchange', () => {
// 路由处理逻辑
})
其中 supportsPushState 来自 vue-router/src/util/push-state.js 的特性检测,确保在不同浏览器环境下选择合适的实现方式。
总结
Hash 模式和 History 模式分别通过 URL 哈希和 HTML5 History API 实现前端路由,核心差异在于 URL 格式、浏览器支持和服务器依赖。开发者应根据项目需求和部署环境选择合适模式,并理解其实现原理以应对复杂场景。
通过阅读 vue-router/src/history/ 目录下的源码,可深入了解路由系统的设计思想,为自定义路由功能或解决复杂路由问题提供基础。官方文档中关于路由模式的说明可参考 docs/v2/vue-router/ 目录下的相关文件。
【免费下载链接】vue-analysis :thumbsup: Vue.js 源码分析 项目地址: https://gitcode.com/gh_mirrors/vu/vue-analysis
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



