#Hash 模式 vs History 模式

发布于:2025-04-14 ⋅ 阅读:(66) ⋅ 点赞:(0)

📌 一、概念对比:Hash 模式 vs History 模式

特性 Hash 模式 History 模式
URL 样式 http://example.com/#/home http://example.com/home
是否刷新页面 ❌ 不会刷新(仅 hash 变化) ✅ 通过 HTML5 API 控制,不刷新
原理 window.onhashchange 监听 # 后的变化 使用 history.pushState()popstate 事件
服务器要求 ❌ 无需服务器配置 ✅ 需要服务端支持(所有路由都重定向到 index.html
SEO 友好 ❌ 不友好 ✅ 更友好
使用场景 本地项目、简单项目 需要完整前端路由的正式项目

💡 二、底层原理代码对比示例

🚀 1. Hash 模式核心原理示意

// 监听 hash 变化
window.addEventListener('hashchange', () => {
  const hash = location.hash.slice(1); // 去掉 #
  renderView(hash);
});

function renderView(route) {
  const app = document.getElementById('app');
  if (route === 'home') {
    app.innerHTML = '<h2>首页</h2>';
  } else if (route === 'about') {
    app.innerHTML = '<h2>关于页</h2>';
  } else {
    app.innerHTML = '<h2>404</h2>';
  }
}

// 初始化加载
window.addEventListener('load', () => {
  const hash = location.hash.slice(1) || 'home';
  renderView(hash);
});

✅ 不刷新页面,只监听 # 的变化。


🎯 2. History 模式核心原理示意

<!DOCTYPE html>
<html>
  <body>
    <a href="/home" data-link>首页</a>
    <a href="/about" data-link>关于</a>
    <div id="app"></div>

    <script>
      // 拦截 <a> 的点击,阻止默认跳转
      document.addEventListener('click', e => {
        if (e.target.matches('[data-link]')) {
          e.preventDefault();
          const path = e.target.getAttribute('href');
          history.pushState({}, '', path);  // 改变地址栏路径
          render(path); // 渲染页面内容
        }
      });

      // 后退/前进时触发
      window.addEventListener('popstate', () => {
        render(location.pathname);
      });

      // 页面初次加载
      window.addEventListener('load', () => {
        render(location.pathname);
      });

      function render(route) {
        const app = document.getElementById('app');
        if (route === '/home') app.innerHTML = '🏠 这是首页';
        else if (route === '/about') app.innerHTML = 'ℹ️ 这是关于页';
        else app.innerHTML = '❌ 404 Not Found';
      }
    </script>
  </body>
</html>

🔍 这体现了 History 模式的本质:利用浏览器历史记录栈 + 路径变化不刷新页面,但刷新时依赖服务端路径处理。

✅ 使用了 history.pushState,可以改变地址栏但不刷新页面。需要服务端配置:所有路径都返回 index.html


🔍 三、Vue Router 中的使用

// router/index.js
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'

const routes = [
  { path: '/home', component: Home },
  { path: '/about', component: About }
]

// 💡 选择不同模式
const router = createRouter({
  history: createWebHashHistory(), // Hash 模式
  // history: createWebHistory(), // History 模式
  routes
})

export default router

⚠️ 四、总结:什么时候用哪个?

场景 推荐模式
开发阶段或无后端支持 Hash 模式
SEO 需求 / 更自然的 URL History 模式(需配置 Nginx/Apache)





💡 核心区别:URL变化的本质机制不同

区别点 Hash 模式 History 模式
触发方式 改变 location.hash(即 # 后的部分) 使用 history.pushState()replaceState()
页面刷新? ❌ 永远不会刷新 ✅ 默认不刷新,但如果用户手动输入或刷新,就需要后端支持
URL 示例 http://a.com/#/home http://a.com/home
浏览器行为 hash 改变不会请求服务器 history 改变,如果没有处理,浏览器会向服务器发起请求

📌 从浏览器行为来看本质区别的代码对比

✅ Hash 模式代码:

<!-- hash.html -->
<a href="#/home">首页</a>
<a href="#/about">关于</a>

<script>
window.addEventListener('hashchange', () => {
  console.log('当前 hash:', location.hash);
});
</script>

📍点击链接时,浏览器不会向服务器发送请求,只是修改 # 后的字符串,触发 hashchange


✅ History 模式代码:

<!-- history.html -->
<a href="/home" data-push="true">首页</a>
<a href="/about" data-push="true">关于</a>

<script>
document.addEventListener('click', e => {
  if (e.target.dataset.push) {
    e.preventDefault();
    const path = e.target.getAttribute('href');
    history.pushState({}, '', path);  // 修改 URL,无刷新
    console.log('当前路径:', location.pathname);
  }
});

// 用户点击浏览器的“前进/后退”按钮时
window.addEventListener('popstate', () => {
  console.log('用户前进/后退,当前路径:', location.pathname);
});
</script>

📍浏览器地址栏变化了,但页面没刷新。如果你手动刷新页面,浏览器就会尝试向 /about 发送真实的 HTTP 请求(如果没有服务端配置,会报 404 ❌)。


⚠️ 最明显区别验证方式 ✅

测试操作 Hash 模式 History 模式
🔄 刷新页面 保持页面内容不变,浏览器不会请求服务器 如果没有后端配置,会报 404
📌 浏览器“后退” 会触发 hashchange 会触发 popstate
👀 查看 Network 面板 没有任何请求 如果刷新页面或直接访问某个路径,会发送请求到该路径

🚧 模拟真实后端配置问题(最直观的对比)

✅ Hash 模式部署(如 GitHub Pages)

  • 不管你访问什么 #/xxx,实际请求的永远是 index.html
  • 所以不需要后端配置

⚠️ History 模式部署

  • 用户访问 http://a.com/about
  • 浏览器会发起请求:GET /about
  • 如果服务器没有设置“所有路径都返回 index.html”,就会 404

👀 所以 vue-router 的 history 模式 必须配合服务端 rewrite 规则 才能用!


🎯 总结成一句核心对比:

Hash 模式是前端控制 URL 变化,不涉及服务端请求;History 模式则是真正改变浏览器路径,需要服务端协助处理路径。



网站公告

今日签到

点亮在社区的每一天
去签到