onhashchange只能绑定到window对象,不能写在body标签中;它只响应导航引起的hash变化,不响应location.hash赋值;需手动处理首次加载和IE7等旧环境的轮询降级。

onhashchange 不能直接写在 里——它不是 body 元素的合法事件属性,浏览器会忽略,监听完全失效。
你真正该绑定的地方只有一个:window 对象。
onhashchange 必须绑定到 window,不是 body 或 document
HTML 规范中,onhashchange 是 window 的专属事件处理器, 属于无效写法,连控制台警告都不会抛。实际开发中常见错误就是误以为能像 onclick 那样内联写在标签上。
-
window.onhashchange = handler是最简写法,但只能设一个监听器 -
window.addEventListener('hashchange', handler)更推荐,支持多个监听、可移除(removeEventListener) -
document.onhashchange和document.body.onhashchange均无效果,不要试
location.hash 赋值不触发 onhashchange?这是对的
手动执行 location.hash = '#user' 确实不会触发 hashchange 事件——这不是 bug,是规范行为。该事件只响应“导航意义上的 hash 变更”,比如用户点击锚点、按前进/后退、调用 history.pushState()(且 URL hash 实际变化)等。
立即学习“前端免费学习笔记(深入)”;
- 想确保触发事件,改用
location.href = '#user'(等价于用户点击) - 或封装跳转函数:
function go(path) { history.replaceState(null, '', '#' + path); },再手动调用一次reloadPage() - 别依赖
event.oldURL/event.newURL解析 hash,它们不稳定;始终用window.location.hash读取
兼容 IE8+,但 IE7 及旧 WebView 需轮询 fallback
onhashchange 在 IE8+、Chrome 5+、Firefox 3.6+ 原生可用,但 IE7 完全不支持,部分安卓 4.x WebView 也有兼容问题。若目标环境含这些老版本,必须补轮询逻辑。
- 轮询间隔建议设为
50ms~100ms:太长用户感知延迟,太短影响主线程 - 不要直接调用
window.onhashchange(),它可能是null;应提取成独立函数如handleHashChange()再调用 - 轮询前先检测支持性:
if ('onhashchange' in window),避免重复监听
路由初始化时 hash 可能为空,首次加载要手动处理
页面首次加载带 #login,hashchange 不会触发——因为没“变化”。很多路由逻辑因此漏掉首屏渲染,白屏或显示默认页。
- 必须在绑定监听后,立即手动执行一次路由匹配逻辑
- 例如:
handleHashChange();或router.reloadPage(); - 别只靠事件驱动,初始状态要显式处理
window.location.hash 的读取和 hashchange 的触发时机,是前端路由最易出错的两个耦合点。绕开它们的坑,比写出漂亮封装更重要。



















