history.pushState()是浏览器原生支持的无刷新跳转核心方法,通过操作history对象新增历史记录、更新URL(同源相对或绝对路径),不触发重载;需配合popstate事件监听及手动内容加载实现完整SPA路由。

history.pushState() 是无刷新跳转的核心方法
浏览器原生支持无刷新改变 URL 并记录历史,关键不是替换页面内容,而是操作 history 对象。直接调用 pushState() 即可新增一条历史记录,同时不触发页面重载。
它接受三个参数:state(任意可序列化对象)、title(目前多数浏览器忽略)、url(相对路径或绝对路径,必须同源)。
-
url必须与当前页面同源,跨域会抛出SecurityError -
state会被存入历史栈,后续通过popstate事件读取,不能是函数或 DOM 节点 - 调用后地址栏立即更新,但不会自动请求新页面——你得自己用
fetch或路由逻辑加载内容
history.pushState({ page: 'detail', id: 123 }, '', '/item/123');
监听 popstate 才能响应浏览器前进/后退
用户点击返回按钮或调用 history.back() 时,不会自动还原页面状态。你必须主动监听 popstate 事件,并根据 event.state 重新渲染。
- 该事件只在 history 栈变化且由浏览器导航(非代码跳转)时触发,
pushState和replaceState不会触发它 -
event.state就是之前传入pushState()或replaceState()的第一个参数 - 首次加载页面时不会触发
popstate,需手动检查history.state初始化 UI
window.addEventListener('popstate', (event) => {
if (event.state?.page === 'detail') {
loadItem(event.state.id);
}
});
replaceState() 适合更新当前条目而非新增记录
当需要修改当前 URL 但不想让用户多按一次「后退」才能离开时,用 replaceState() 替代 pushState()。
立即学习“Java免费学习笔记(深入)”;
- 它不增加新历史项,只覆盖当前项的
state和url - 常见于表单筛选后更新 URL 参数、滚动位置保存等场景
- 和
pushState()参数完全一致,只是语义不同
// 比如搜索关键词变更,不希望每次输入都生成一条历史
history.replaceState({ q: 'react' }, '', '/search?q=react');
注意 hash 模式与 HTML5 模式的行为差异
使用 pushState() 需确保服务端支持:所有前端路由路径都应返回同一份 HTML(否则刷新会 404)。若无法控制服务端,可用 hash 模式降级,但它是另一套机制。
-
location.hash = '#/user'不触发页面刷新,也不走pushState流程,监听的是hashchange事件 -
hash改变不会被计入history.state,popstate也不会触发 -
pushState()改变的是 URL 的 path 部分,hash改变的是 fragment,二者互不影响
真正做 SPA 路由时,别混用两种模式;服务端可配置就优先用 HTML5 模式,更干净也利于 SEO。











