前端路由原理:History API 和 Hash 区别

域名注册
域名注册 初级会员超兽战士 👑年卡会员
发布于 2026-10-07 22:07 ·4 浏览 ·0 回复

结论:History API 路由和 Hash 路由的核心区别是:History 改真实路径,刷新或直接访问会向服务器发请求,必须服务端回退到 index.html;Hash 改 # 后的片段,片段不会发给服务器,所以零服务端配置。现代项目优先 History,纯静态托管或需兼容 IE8/IE9 用 Hash。

前端路由(SPA 中用 JS 根据 URL 切换视图,而不向服务器请求新页面)主要靠两套机制:History API(浏览器 history 对象提供 pushState、replaceState、popstate 的接口)和 Hash(URL 中 # 后面的片段标识符)。

History API 和 Hash 路由到底差在哪?

结论:差在 URL 形态、请求行为、监听事件、兼容性与部署成本。

History 模式 URL 是 https://example.com/user/1;Hash 模式 URL 是 https://example.com/#/user/1。History 用 history.pushState(state, '', '/user/1') 改地址栏,页面不刷新、不请求服务器;但刷新或直接访问 /user/1 时,浏览器会向服务器请求这个真实路径。Hash 改 location.hash 或点击 href="#/user/1",只会触发 hashchange,HTTP 请求里只有 /,不会带 #/user/1。

监听事件也不同:History 监听 popstate,Hash 监听 hashchange。兼容性上,history.pushState 从 IE10 开始支持,hashchange 从 IE8 开始支持;现代浏览器两者都支持。

History API 路由怎么做?

结论:用 pushState/replaceState 改 URL,用 popstate 监听后退前进,用服务端 fallback 兜底刷新。

最小步骤:

  1. 拦截站内链接点击,阻止默认跳转,调用 history.pushState。
  2. 监听 popstate,根据 location.pathname 或 event.state 渲染视图。
  3. 首次加载时手动调用一次 render(location.pathname)。
  4. 服务端把未知路径回退到 index.html。
document.addEventListener('click', e => {
  const a = e.target.closest('a[data-router]');
  if (!a) return;
  e.preventDefault();
  const path = a.getAttribute('href');
  history.pushState({ path }, '', path);
  render(path);
});

window.addEventListener('popstate', e => {
  render(e.state?.path || location.pathname);
});

render(location.pathname);

注意:pushState 不会触发 popstate,所以必须手动 render。replaceState 不新增历史记录,适合登录后重定向。Nginx 要加:

location / {
  try_files $uri $uri/ /index.html;
}

Apache 则用 .htaccess 把不存在的文件和目录重写到 index.html。

Hash 路由怎么做?

结论:监听 hashchange 并解析 location.hash 即可,不需要服务端配置。

步骤:

  1. 链接写成 <a href="#/user/1">。
  2. 监听 hashchange 和首次 load。
  3. 用 location.hash.slice(1) 拿到 /user/1,再匹配路由。
window.addEventListener('hashchange', render);
window.addEventListener('load', render);

function render() {
  const path = decodeURIComponent(location.hash.slice(1) || '/');
  // 根据 path 渲染视图
}

改变 hash 会新增历史记录,后退前进会触发 hashchange。要替换当前记录而不是新增,可以用 location.replace('#/user/1')。中文 hash 需要 decodeURIComponent。

为什么 History 模式刷新会 404?

结论:因为 /user/1 是真实路径,刷新时服务器会去磁盘找这个文件,找不到就返回 404。Hash 的 #/user/1 中 # 后内容不会出现在 HTTP 请求里,服务器只收到 /,所以不会 404。

纯静态托管如果没有重写规则,只能用 Hash。比如把打包文件上传到普通对象存储或 CDN,直接访问 /user/1 会 404。History 模式要求部署环境支持 try_files、Netlify _redirects、Vercel rewrites 这类回退配置。

选 History 还是 Hash?

结论:有服务端配置且在意 SEO 选 History;纯静态、无重写、兼容老浏览器选 Hash。

History 的 URL 干净,爬虫能抓取真实路径,SEO 更友好;Hash 的 # 后内容传统爬虫可能忽略,SEO 较弱。部署上,History 需要服务端或托管平台支持回退,Hash 上传静态文件即可。兼容上,History 需要 IE10+,Hash 在 IE8 可用。Vue Router 用 createWebHistory 或 createWebHashHistory,React Router 用 BrowserRouter 或 HashRouter。

收束一下:History 和 Hash 的本质区别是“路径是否真实发给服务器”。History 体验好、SEO 好,但必须配 fallback;Hash 部署简单、兼容更老,但 URL 带 #、SEO 弱。选型先看部署环境,再看兼容和 SEO 要求。

版权声明:本文来自 GJ站长论坛《前端路由原理:History API 和 Hash 区别》
原文链接:https://www.gj0.com/thread-581.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。

全部回复 0

还没有回复,来抢沙发~