必须同时监听 onload 和 hashchange 事件,因为 hashchange 仅在 hash 值变化后触发,不包括页面首次加载时已存在的 hash;需在 onload 时手动执行一次路由处理,并用 location.hash.slice(1) 安全提取路径。

直接用 window.addEventListener("hashchange", handler) 就能实现,但只监听这个事件会漏掉首次加载——用户访问 https://example.com/#/about 时页面空白,因为 hashchange 不会在页面 load 时触发。
为什么 onload + hashchange 必须一起用
浏览器只在 hash 值**变化后**触发 hashchange,不包括初始加载。比如用户从书签或外链直接打开带 hash 的 URL,location.hash 已经是 "#/about",但事件没发生过。
- 必须在
load时手动调用一次路由处理函数 - 不能只写
window.onhashchange = handler—— 它会被后续赋值覆盖,且无法同时绑定多个监听器 -
addEventListener是唯一安全的绑定方式
location.hash 取值常见错误
location.hash 返回的是带 # 的完整字符串,比如 "#/user/123",不是 "/user/123",也不是空字符串 ""。
- 正确截取路径:用
location.hash.slice(1),不是.substr(1)(已废弃)或正则匹配 - 空 hash 时
slice(1)返回空字符串"",需默认设为"/"或其他兜底路径 - 不要用
=== "#/about"直接比对,要先剥离#再比对路径
跳转和 DOM 更新怎么写才不出错
所有跳转统一用 location.hash = value,不要混用 history.pushState;视图更新推荐用 class 切换而非 innerHTML 替换,避免事件监听器丢失。
立即学习“前端免费学习笔记(深入)”;
- 按钮跳转示例:
<button onclick="location.hash='/profile'">个人页</button> - DOM 更新建议用
document.body.classList.toggle("view-profile", path === "/profile")配合 CSS 控制显隐 - 如果必须操作 innerHTML,记得重新绑定事件(比如表单 submit、按钮 click),否则下次点击无效
- 避免在 handler 里重复查询
document.getElementById("app"),提取为常量复用
最易被忽略的是首次加载时没执行路由匹配,以及把 location.hash 当成干净路径直接用——这两个点出错,整个路由就卡死在空白页。其他逻辑其实就几行代码,关键是边界条件得兜住。



















