pushState 一推,URL 改了;popstate 一监听,路由就跳了。原来不用刷新也能换页面,我真是学疯了!
👋 前言:小白一枚,但我有个「大厂梦」
作为一个正学 JavaScript 的小白,每次打开 B 站/掘金,看那些大佬用 React写路由跳转,URL 变了,页面内容也变了,但页面竟然没刷新?
我当时直接惊了:这不是魔法吗!?
后来我才知道,这背后其实是前端路由的秘密武器 ------ History 模式 SPA(Single Page Application) 。
今天我就来讲讲我对它的理解,既当学习笔记,也当成长记录。希望你也能和我一样,从小白慢慢走向大厂!
🧠 什么是 History 模式 SPA?
SPA,全称 Single Page Application,翻译成中文就是"单页应用"。
整个网站只用一个 HTML 页面,所有页面的内容都是通过 JavaScript 动态切换出来的,页面不刷新,体验丝滑到飞起!
而 History 模式,就是 SPA 中用来实现"URL 变化不刷页面"的一种技术方案,依靠的是浏览器提供的 History API,尤其是:
pushState()
replaceState()
popstate
事件
📍URL 变化的魔法就是这样来的!
以前你用 <a href="/about">
,点击就会刷新整个页面 ------ 那是传统的多页应用(MPA)。
而使用了 History 模式的 SPA,页面不会刷新,URL 却能改变,给用户一种"好像真的跳了页面"的感觉,这种体验就是现代前端框架的底层魔法。
🧩 Hash 路由 vs History 路由,到底怎么选?
这里我还得给你补充点实用干货------Hash 路由和 History 路由的区别和适用场景。想学路由,这两个必须懂!
什么是 Hash 路由?
简单说,就是 URL 中用 #
(井号)后面带路径,比如:
bash
http://example.com/#/about
浏览器默认不会把 #
及后面的部分发送给服务器,也不会刷新页面。
Hash 路由优点:
- 兼容性超好:支持所有浏览器,连 IE 都不怕
- 部署简单:不用后端额外配置,服务器只管返回主页面即可
- 简单粗暴:刷新页面不会 404
Hash 路由缺点:
- URL 不够美观,带着丑丑的
#
- SEO 不友好(虽然现在搜索引擎逐渐支持,但历史包袱仍在)
什么是 History 路由?
基于浏览器的 History API,URL 就像正常路径一样:
js
http://example.com/about
路由跳转时,地址栏改变,但不会刷新页面。
History 路由优点:
- URL 干净漂亮,符合正常网站路径习惯
- 更符合 SEO,支持服务端渲染(SSR)
- 更灵活,能自由控制浏览器历史栈
History 路由缺点:
- 需要后端支持,配置服务器"所有路径都返回 index.html",否则刷新会 404
- 兼容性比 Hash 略差,但主流现代浏览器都支持了
总结对比
- 兼容性:Hash 路由 > History 路由
- URL 美观度:History 路由 > Hash 路由
- SEO 支持:History 路由 > Hash 路由
- 部署复杂度:Hash 路由 < History 路由
💡 核心知识点全解析
✅ 1. history.pushState()
这是修改地址栏但不刷新页面的关键 API。
js
history.pushState({ page: 'about' }, '', '/about');
含义很简单:
- 改变 URL:地址栏变成了
/about
- 页面不会刷新(JavaScript 控制渲染)
- 浏览器历史记录多了一条(用户可以点"返回"回去)
✅ 2. history.replaceState()
和 pushState
类似,也是改 URL,但不会新增历史记录,而是替换当前记录。
js
history.replaceState({ page: 'home' }, '', '/home');
什么时候用?
- 登录成功后不想让用户点击"返回"退回登录页;
- 删除 URL 上的一次性参数,比如
/dashboard?token=123
; - 页面初始化时设置路径,但不希望用户能"返回"到空白页。
✅ 3. popstate
事件
这个事件会在你点击浏览器的"返回"或"前进"按钮时触发,或者你调用 history.back()
/ forward()
。
js
window.addEventListener('popstate', (event) => {
console.log('popstate 触发了,状态是:', event.state);
});
它的作用就是:让你有机会在用户返回/前进时更新页面内容!
结合 event.state
(就是你之前 pushState 时传进去的状态),你就能知道现在要显示哪一页内容啦!
🛠 手把手写一个迷你 SPA 路由器
终于到了实践环节,来点硬核干货!
js
<!-- index.html -->
<button id="home">Home</button>
<button id="about">About</button>
<div id="view"></div>
<script>
const view = document.getElementById('view');
function render(path) {
if (path === '/about') {
view.innerHTML = '<h2>这是关于页</h2>';
} else {
view.innerHTML = '<h2>这是首页</h2>';
}
}
document.getElementById('home').addEventListener('click', () => {
history.pushState({ path: '/' }, '', '/');
render('/');
});
document.getElementById('about').addEventListener('click', () => {
history.pushState({ path: '/about' }, '', '/about');
render('/about');
});
// 初始化加载
render(location.pathname);
// 监听返回/前进按钮
window.addEventListener('popstate', (event) => {
const path = event.state?.path || location.pathname;
render(path);
});
</script>
它做了什么?
- 点击按钮不刷新页面,地址栏 URL 改变了;
- 页面内容手动更新;
- 点击浏览器"后退"按钮,页面内容也会同步回退!
这就是真·手写路由的第一步!是不是觉得也没那么难?
🧠 History 模式 SPA 的优缺点
既然它这么厉害,那有没有坑呢?当然有!
✅ 优点:
- URL 美观:没有
#
,直接/about
/user/123
- 更符合用户习惯:用户可以收藏、分享、前进后退
- 支持 SEO(配合 SSR 服务端渲染)
❌ 缺点:
-
需要后端配合部署!
- 如果用户刷新
/about
页面,服务器会直接找/about
路径,如果没有配置,会返回 404! - 需要配置:所有路径都 fallback 到
index.html
- 如果用户刷新
📦 解决方式(以 nginx 为例):
nginx
location / {
try_files $uri /index.html;
}
✅ 总结:这是 SPA 的核心,也是通往大厂的第一道门
如果你正在学前端、追求更高的技术深度、希望进大厂,那理解 History 模式的 SPA 路由机制是你必须迈过的一道门槛!
本篇你已经学会了:
- 什么是 SPA?什么是 History 模式?
- Hash 路由和 History 路由的区别和适用场景
pushState
和replaceState
的区别popstate
监听返回跳转- 如何手写一个简单的前端路由
- History 模式的优缺点与部署注意事项
🚀 写在最后:我不再是只会写 alert() 的人了!
当我第一次点击"关于"页面,看到地址栏悄咪咪地变成 /about
,页面跟着变了,但没有刷新......那一刻我知道,我已经不再是那个只会写 alert('hello world')
的小白了!
这只是前端成长之路上的一小步,但你、我、我们都在路上。
如果这篇文章有帮到你,记得点赞 👍 收藏 ⭐ 留言 ✍️ 一波!