pushState 改变 URL 且不刷新页面,仅更新浏览器历史栈并触发 popstate 事件(需手动监听处理),state 参数可存状态对象,title 被忽略,url 需同源;SPA 部署时服务端必须配置 fallback 返回 index.html,否则直接访问会 404。

pushState 不会触发页面刷新
pushState 的核心作用就是**改变 URL 且不重新加载页面**。它只是把新状态推入浏览器历史栈,不会触发 load、DOMContentLoaded 或任何导航类事件。页面 DOM、JS 执行上下文、网络连接、定时器全部保持原样。
常见误解是把它和 window.location.href = 'xxx' 混淆——后者会立刻发起新导航并刷新;而 pushState 是纯 JS 层的同步操作,快到几乎察觉不到延迟。
- 调用后
window.location.href立即更新,但页面内容不变 - 用户点击「后退」时,也不会刷新,而是触发
popstate事件 - 服务端完全无感知:这个 URL 变化只存在于前端,除非用户手动刷新或直接访问该地址
必须手动处理 popstate 才能响应后退/前进
因为 pushState 不刷新,所以浏览器「后退」到该状态时,不会自动重绘页面。你得监听 popstate 并自己更新内容,否则用户看到的还是旧视图。
注意:首次加载页面时(非通过后退/前进进入),popstate **不会触发**;只有历史跳转才会触发。
立即学习“Java免费学习笔记(深入)”;
window.addEventListener('popstate', (event) => {
// event.state 是 pushState 传入的第一个参数(可为 null)
console.log('当前状态:', event.state);
// 这里要手动渲染对应路由的内容,比如更新 DOM、发起 API 请求等
});pushState 的三个参数容易填错
pushState(state, title, url) 中:
- state 是任意可序列化的对象(如 {page: 'detail', id: 123}),会随历史项存储,后续 popstate 事件中可取回
- title 当前所有主流浏览器都忽略它,传空字符串 '' 最安全
- url 必须与当前域同源,且不能跨协议/端口;可以是相对路径(如 '/posts/42')或绝对路径(如 'https://example.com/posts/42'),但不能是完整跨域 URL
- 错误示例:
pushState({}, '', 'https://evil.com/hack')→ 报错SecurityError - 错误示例:
pushState({}, 'My Page', '/')在https://a.com/page下执行 → 合法,URL 变为https://a.com/ - 正确习惯:始终用相对路径,避免硬编码域名
SPA 路由必须配合服务端 fallback
单页应用用 pushState 实现前端路由(如访问 /user/5 不刷新),但有个关键陷阱:如果用户直接在地址栏输入 /user/5 并回车,请求会发到服务端——而服务端通常没有这个真实路径,返回 404。
解决办法是让服务端对所有前端路由路径,都返回同一份 HTML(通常是 index.html),再由前端 JS 解析当前 URL 并渲染对应视图。
- Nginx 配置示例:
try_files $uri $uri/ /index.html; - Vercel / Netlify 默认开启 SPA fallback
- 开发服务器(如 Vite、Webpack Dev Server)通常自带,但生产部署时极易遗漏
这个环节一旦漏掉,pushState 在直接访问或刷新时就会彻底失效——不是 JS 问题,是服务端没兜住。










