pushState 改变 URL 且不刷新页面,仅更新浏览器历史栈并触发 popstate 事件(需手动监听处理),state 参数可存状态对象,title 被忽略,url 需同源;SPA 部署时服务端必须配置 fallback 返回 index.html,否则直接访问会 404。
pushState 的核心作用就是**改变 URL 且不重新加载页面**。它只是把新状态推入浏览器历史栈,不会触发 load、DOMContentLoaded 或任何导航类事件。页面 DOM、JS 执行上下文、网络连接、定时器全部保持原样。
常见误解是把它和 window.location.href = 'xxx' 混淆——后者会立刻发起新导航并刷新;而 pushState 是纯 JS 层的同步操作,快到几乎察觉不到延迟。
window.location.href 立即更新,但页面内容不变popstate 事件因为 pushState 不刷新,所以浏览器「后退」到该状态时,不会自动重绘页面。你得监听 popstate 并自己更新内容,否则用户看到的还是旧视图。
注意:首次加载页面时(非通过后退/前进进入),popstate **不会触发**;只有历史跳转才会触发。
window.addEventListener('popstate', (event) => {
// event.state 是 pushState 传入的第一个参数(可为 null)
console.log('当前状态:', event.state);
// 这里要手动渲染对应路由的内容,比如更新 DOM、发起 API 请求等
});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/
单页应用用 pushState 实现前端路由(如访问 /user/5 不刷新),但有个关键陷阱:如果用户直接在地址栏输入 /user/5 并回车,请求会发到服务端——
而服务端通常没有这个真实路径,返回 404。
解决办法是让服务端对所有前端路由路径,都返回同一份 HTML(通常是 index.html),再由前端 JS 解析当前 URL 并渲染对应视图。
try_files $uri $uri/ /index.html;
这个环节一旦漏掉,pushState 在直接访问或刷新时就会彻底失效——不是 JS 问题,是服务端没兜住。