哈希模式不能替代 history 路由,仅适用于纯静态页等无需 SEO/SSR 的场景;其依赖 location.hash 和 hashchange 事件实现前端路由,但服务端不可见、刷新易 404、参数解析繁琐且易踩初始哈希未处理、编码未解码、与框架 Router 冲突三坑。

不能直接替代,但可以用作简易前端路由的降级方案——前提是接受 URL 不干净、SEO 友好性差、服务端不配合时刷新即 404 这些硬伤。
哈希模式(location.hash)为什么能“模拟”路由
浏览器不会把 # 后的内容发给服务端,所以切换 #about 或 #user/123 不触发页面重载;同时 hashchange 事件能监听变化,配合 DOM 操作就能手动切换视图。
- 适用场景:纯静态站点、内部工具页、原型演示、不需 SSR/SEO 的后台管理页
- 关键限制:服务端无法感知哈希值,Nginx/Apache 配置再全,刷新
https://site.com/#user/123仍会请求/,必须靠前端 HTML 加载后二次解析location.hash恢复状态 - 兼容性无压力,IE8+ 都支持
hashchange,但要注意 IE9- 需监听onhashchange而非addEventListener('hashchange', ...)
history.pushState() 和哈希的根本区别在哪
核心是 URL 是否真实参与导航流程:pushState 修改的是浏览器地址栏完整路径(如 /user/123),服务端可配置 fallback(如 Nginx 的 try_files $uri $uri/ /index.html;),刷新时资源能正常加载;而哈希只是客户端标记,服务端完全看不见。
- 性能上没差别,但体验断层明显:哈希路由下按 F5,白屏几秒再渲染;
pushState路由刷新后 HTML 已加载完毕,JS 立即接管,更接近原生页面跳转感 - 参数处理差异大:
location.hash是字符串,需手动slice(1)+split('/')解析;pushState配合URL构造函数或URLSearchParams更可靠,比如new URL('/user/123?tab=info', location.href).pathname - 前进/后退行为一致,但哈希路由无法通过
history.state携带结构化数据,只能塞进 URL 字符串里编码,容易出错
用哈希做路由时最容易踩的三个坑
不是写不出来,而是上线后才发现逻辑裂开。
立即学习“前端免费学习笔记(深入)”;
- 未监听初始哈希:页面首次加载时
hashchange不触发,必须手动执行一次handleRoute(location.hash) - 哈希值未 decode:用户从外部链接带
#user%2F123进来,location.hash是原始编码串,直接split('/')会切出%2F,得先decodeURIComponent(hash.slice(1)) - Vue/React 等框架里混用哈希路由和框架 Router:比如在 Vue Router 中启用
mode: 'hash',又自己监听hashchange手动更新,导致重复渲染或状态不同步
哈希路由不是过时技术,而是权衡取舍后的选择。真正麻烦的从来不是怎么写,而是当产品突然要求加分享链接、做微信内嵌页、对接百度统计时,发现所有 # 后的路径在抓取端全失效——这时候再切 history 模式,就得同步改服务端配置、补 fallback、处理相对路径引用,成本远超预期。



















