单页路由可用hashchange或popstate实现:hashchange兼容性好,通过location.hash读写#后路径;popstate需服务端fallback和拦截a标签,配合pushstate/replacestate操作真实路径。
直接用原生 javascript 实现单页路由,核心就是靠 hashchange 和 popstate 两个事件监听 url 变化,并配合对应 api 修改地址栏——不刷新页面,只换内容。
hashchange 路由:兼容好、开箱即用
URL 中 # 后面的部分叫 hash,修改它不会触发页面重载,浏览器也不会把 hash 发给服务端。所有主流浏览器(包括 IE8)都支持 hashchange 事件。
- 监听方式:用
window.addEventListener('hashchange', handler),每次 hash 改变(点击链接、前进/后退、脚本赋值)都会触发 - 读取当前路径:
location.hash返回带 # 的字符串(如#/user),通常用.slice(1)去掉 # 再匹配 - 主动跳转:直接赋值
location.hash = '/about'即可,会自动触发 hashchange - 首次加载要手动执行一次处理函数,因为页面初始化时不会触发 hashchange
popstate 路由:URL 干净,但需服务端兜底
HTML5 History API 允许操作真正的路径(如 /product/123),用 pushState() 或 replaceState() 修改 URL 不刷新页面,再用 popstate 监听浏览器前进/后退。
-
pushState(state, title, url):向历史栈添加新条目,用户可点「返回」回到上一页 -
replaceState():替换当前条目,适合表单提交后跳转,避免重复提交 -
popstate只在用户点击前进/后退按钮,或调用history.back()等时触发;用pushState改 URL 不会触发它 - 服务端必须配置 fallback:所有非静态资源请求(如
/user)都要返回index.html,否则刷新页面会 404
必须拦截 a 标签点击,防止默认跳转
哪怕你写了 pushState,用户点普通 <a href="/user"></a> 还是会整页刷新。得全局代理点击事件:
- 用事件委托绑定到
document,捕获所有点击 - 判断目标链接是否同源、是否为相对路径(
new URL(href).origin === location.origin) - 排除
target="_blank"、download、javascript:等特殊链接 - 符合条件的,调用
event.preventDefault(),再执行pushState + 渲染
渲染逻辑要统一入口,避免重复代码
不管从 hashchange、popstate 还是脚本跳转进来,最终都该走同一个路由分发函数:
- 定义一个路由表对象,键是路径(如
'/home'或'#/about'),值是渲染函数 - 渲染函数负责更新 DOM,比如填入
innerHTML或挂载组件 - 状态对象(
pushState的第一个参数)可存页面所需数据,避免二次解析 URL - 错误路径要有兜底,比如显示 404 或跳转首页
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











