前端路由原理 history 与 hash 的差异
晴空白T
6 分钟阅读
前端路由原理 history 与 hash 的差异
history 与 hash 解决的是同一个问题:在不刷新整页的前提下,让 URL 变化映射到视图切换。两者的根本差异不在 API,而在 URL 长什么样、以及刷新时服务端需要做什么。很多团队在选型时只盯着"URL 好不好看",上线后才发现 history 模式在服务端少配了一条兜底规则,结果一刷新就 404。理解原理比记住 API 更重要。
为什么需要路由拦截
浏览器默认的 URL 跳转会发起整页请求并重建 DOM,成本高且丢失前端状态。单页应用的路由靠监听 URL 变化、手动渲染对应组件来避免整页刷新。无论哪种模式,本质都是一张"URL 状态 -> 渲染函数"的映射表。路由库做的事情,就是在这张表之上加上嵌套、参数解析、懒加载等能力,但内核始终是监听、查表、渲染这三步。
const routes = {
'/': renderHome,
'/user': renderUser,
'/about': renderAbout,
};
function render(path) {
const fn = routes[path] || renderNotFound;
app.innerHTML = fn();
}
hash 模式:靠 # 后的片段
hash 是 URL 中 # 之后的部分。修改它不会触发页面跳转,也不会向服务端发请求。监听靠 hashchange 事件。这是早期单页应用能用纯静态托管跑起来的根本原因——服务端永远只收到 /,剩下的全是前端的事。
window.addEventListener('hashchange', () => {
render(location.hash.slice(1) || '/');
});
location.hash = '/user';
刷新 /#/user 时,浏览器实际请求的是 /,服务端只需返回同一份 HTML,路由由前端解析。边界条件:hash 里不能放需要被服务端读取的信息;# 后的内容不会被带进请求行,因此天然适合纯前端路由。但 hash 也会带来可读性差、无法利用服务端真实路径做缓存分层、部分统计工具对 hash 路由识别不友好等问题。
history 模式:干净的 URL 背后是服务端配合
HTML5 提供 pushState/replaceState 修改路径而不刷新,靠 popstate 监听。注意 pushState 本身不触发 popstate,需在调用后手动 render,这是新手最常踩的"点了没反应"的来源。
function navigate(path) {
history.pushState({}, '', path);
render(path);
}
window.addEventListener('popstate', () => {
render(location.pathname);
});
navigate('/user');
代价是:刷新 /user 时浏览器会真实请求 /user,若服务端没有兜底返回同一份 HTML,就会 404。这是 history 模式最容易踩的坑——上线前要确认服务端对所有前端路由返回应用入口页,或做路径重写。开发环境里常见 dev server 默认帮你做了这件事,所以本地没问题、上线就崩的情况极为常见,排查时要先确认服务端兜底而非怀疑前端代码。
两个容易忽略的边界
- 相对路径基准:history 模式下原生
<a> 若写成相对路径,会基于当前 pathname 拼接,导致层级错误;建议统一用绝对路径,或由路由库处理 basename,尤其当应用部署在子路径(如 /app/)下时,basename 配错会让所有路由偏移。
- hash 的解析:
location.hash 自带部分解码,? 和 & 在 hash 内不会拆分查询串。需要自行解析 search 参数时得手动处理,不能依赖 URLSearchParams 直接读全局 search。很多项目因此把查询参数也塞进 hash,需要一套独立的解析函数,否则拿到的参数是空的。
- 滚动恢复:history 模式可以借助
history.scrollRestoration 控制前进后退时的滚动位置,hash 模式则需自己记录每个 hash 对应的滚动偏移。
怎么选
hash 模式零服务端改造,适合静态托管、对 URL 美观不敏感、或部署环境无法改服务端配置的场景。history 模式 URL 更干净、利于分享与 SEO,但需要服务端兜底。移动端 H5 嵌在原生 WebView 里时,部分旧容器对 history 支持不稳,hash 反而更稳妥。经验上,能用 history 且服务端可控就优先 history;否则 hash 省心。选型时把"上线后服务端怎么配"一并考虑,比单纯看 URL 美观更有价值。两种模式在绝大多数业务里都能跑通,真正决定体验的是路由表本身是否清晰、参数校验是否到位。
浏览 0
点赞 0
评论 0