location.hash变化不触发页面刷新但可被javascript捕获,是hash路由核心前提;需手动处理首次加载和锚点干扰,统一用window.location.hash修改,禁止与pushstate混用。

location.hash 变化不触发页面刷新,但能被 JavaScript 捕获——这是实现前端 Hash 路由最核心的前提。不需要框架、不依赖服务器配置,原生 JS 就能跑起来,适合快速验证或轻量级单页场景。
监听 hashchange 事件但页面首次加载不触发?
浏览器只在用户点击链接、脚本修改 location.hash 后才触发 hashchange,页面刚打开时它根本不会响。这意味着:如果 URL 是 https://example.com/#/user,你没手动处理,renderView() 就永远不会执行。
必须在初始化阶段主动读取一次:
- 用
location.hash.slice(1)获取当前哈希路径(去掉#) - 调用路由处理函数,比如
router.go(location.hash.slice(1) || '/') - 别用
document.location.href = '#/xxx'改 hash,它会多加一条历史记录 - 推荐统一用
window.location.hash = '/xxx',语义清晰且行为可预测
pushState 和 hash 混用会导致路由丢失
有人想“升级”路由,一边保留 hash 逻辑,一边偷偷调用 history.pushState。结果是:hashchange 完全不响应,因为 URL 的 hash 部分根本没变。
Hash 路由和 History 路由是两套互斥机制,不能混搭:
- 用了
hashchange,就只认#后面的值,其他任何 URL 变化都与它无关 - 如果你改了
pathname或search,但没动hash,hashchange不会触发 - 微前端里子应用启用 hash 模式,正是为了隔离主应用的 history 操作,避免冲突
服务端无需配置,但要注意锚点跳转干扰
Hash 路由天然兼容静态服务器,部署零成本。但有个现实问题:页面内普通锚点链接(比如 <a href="#section2"></a>)也会改 location.hash,从而误触路由逻辑。
应对方式很直接:
- 约定所有路由路径以
/开头,比如#/home、#/about;而锚点用纯 ID,如#section2 - 路由处理函数中加判断:
if (hash.startsWith('/')) { /* 处理路由 */ } else { /* 忽略,留给原生锚点行为 */ } - 避免给非路由用途的元素设置
id为home、about这类易混淆名
真正容易被忽略的不是怎么写监听器,而是首次加载和锚点共存时的边界处理。很多人写了 hashchange 监听,却忘了页面一开就要 render,也忘了 #top 这种合法哈希值不该进路由系统——这些细节不补上,上线后就会出现“点链接正常,直接打开空白”或“点标题跳转错乱”的问题。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











