前端路由原理:History API 和 Hash 区别
结论: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 兜底刷新。
最小步骤:
- 拦截站内链接点击,阻止默认跳转,调用
history.pushState。 - 监听
popstate,根据location.pathname或event.state渲染视图。 - 首次加载时手动调用一次
render(location.pathname)。 - 服务端把未知路径回退到
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 即可,不需要服务端配置。
步骤:
- 链接写成
<a href="#/user/1">。 - 监听
hashchange和首次load。 - 用
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 要求。
原文链接:https://www.gj0.com/thread-581.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。