Vue Router 中 Hash和 History 模式的核心区别、使用场景

 更新时间:2026年01月05日 10:06:59   作者:涔溪  
文章详细介绍了VueRouter中Hash模式和History模式的核心区别、底层原理、使用场景及部署注意事项,文章还提供了实战部署的解决方案和选型建议,感兴趣的朋友跟随小编一起看看吧

深入理解 Vue Router 中 Hash 模式History 模式 的核心区别、底层原理、使用场景及部署注意事项,我会从「本质→原理→实战→对比→问题解决」全维度超详细讲解,结合你的项目场景(比如之前部署 History 模式报 404)帮你彻底吃透。

一、先搞懂:前端路由的核心本质

Vue 是单页应用(SPA),整个项目只有一个 index.html 文件。前端路由的核心目的:通过 JavaScript 监听 URL 变化,不刷新页面的前提下,动态渲染不同的组件,模拟 “多页面跳转” 的体验(无需向后端发起新的页面请求)。

Hash 模式和 History 模式是实现前端路由的两种技术方案,核心差异在于「URL 表现形式」「底层实现原理」「服务器部署要求」。

二、Hash 模式(哈希模式)

1. 核心定义

Hash 模式是利用 URL 中 # 后面的「哈希值」实现路由跳转,# 是浏览器的锚点标识,哈希值不会被发送到服务器

  • 示例 URL:http://yourdomain.com/#/proOrder
  • 其中 #/proOrder 就是哈希路由,# 后面的内容完全由前端控制。

2. 底层实现原理

(1)核心 API:window.onhashchange

浏览器天生支持监听 # 后面内容的变化,触发 hashchange 事件,前端可在该事件中判断哈希值,渲染对应组件:

// 原生 JS 模拟 Hash 路由核心逻辑
window.addEventListener('hashchange', () => {
  // 获取当前哈希值(去掉 #)
  const hash = window.location.hash.slice(1); 
  // 根据哈希值渲染不同组件
  if (hash === '/proOrder') {
    renderProOrderComponent();
  } else if (hash === '/home') {
    renderHomeComponent();
  }
});

(2)路由跳转的本质

  • 点击 <router-link to="/proOrder"> 时,Vue Router 会修改 window.location.hash = '#/proOrder'
  • 该操作只会改变 URL 的哈希部分,不会触发浏览器的页面刷新,也不会向服务器发请求。

3. Vue Router 中配置 Hash 模式

// router/index.ts
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
const routes: RouteRecordRaw[] = [/* 你的路由规则 */];
const router = createRouter({
  history: createWebHashHistory(import.meta.env.BASE_URL), // 核心:Hash 模式
  routes
});
export default router;

4. 核心特点(优缺点)

优点缺点
1. 无需后端配置:哈希值不发服务器,直接访问 http://xxx.com/#/proOrder 不会 404;2. 兼容性极好:支持所有浏览器(包括 IE6/7/8);3. 开发便捷:本地 / 线上部署无需协调后端;1. URL 不美观:带 # 符号,用户体验略差;2. SEO 不友好:部分搜索引擎爬虫会忽略 # 后的内容,影响页面收录;3. 锚点冲突:若页面内有原生锚点(如 <a href="#top">),会和路由哈希冲突;

三、History 模式(HTML5 历史模式)

1. 核心定义

History 模式基于 HTML5 新增的 History API 实现,URL 无 #,和传统后端路由的 URL 格式一致,哈希值会被完整发送到服务器

  • 示例 URL:http://yourdomain.com/proOrder(和后端路由格式完全一致)
  • 该模式是现代前端项目的主流选择(追求 URL 美观、SEO 友好)。

2. 底层实现原理

(1)核心 API:HTML5 History API

  • history.pushState(state, title, url):修改 URL 且不发送请求,添加一条历史记录;
  • history.replaceState(state, title, url):修改 URL 且不发送请求,替换当前历史记录;
  • window.onpopstate:监听浏览器的「回退 / 前进」按钮,触发状态变化。

(2)路由跳转的本质

// 原生 JS 模拟 History 路由核心逻辑
// 点击跳转按钮时
document.querySelector('#toProOrder').addEventListener('click', (e) => {
  e.preventDefault(); // 阻止默认a标签跳转
  // 修改 URL 为 /proOrder,不发请求
  history.pushState({}, '', '/proOrder');
  // 手动渲染对应组件
  renderProOrderComponent();
});
// 监听回退/前进
window.addEventListener('popstate', () => {
  const path = window.location.pathname;
  if (path === '/proOrder') {
    renderProOrderComponent();
  }
});

⚠️ 关键:pushState 只是修改 URL,不会触发页面刷新,但直接访问 / 刷新 http://xxx.com/proOrder 时,浏览器会向服务器发送该路径的请求—— 这也是你之前部署报 404 的核心原因!

3. Vue Router 中配置 History 模式

// router/index.ts(你的原有配置)
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
const routes: RouteRecordRaw[] = [/* 你的路由规则 */];
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL), // 核心:History 模式
  routes
});
export default router;

4. 核心特点(优缺点)

优点缺点
1. URL 美观:无 #,符合用户对 URL 的认知习惯;2. SEO 友好:完整 URL 会被搜索引擎收录,利于网站优化;3. 无锚点冲突:和页面内原生锚点(如 #top)互不干扰;1. 需要后端配置:直接访问子路由(如 /proOrder)会触发服务器请求,服务器未配置时返回 404;2. 兼容性一般:仅支持 IE10+ 及现代浏览器;3. 部署成本高:需协调后端修改 Nginx/Apache 配置;

四、Hash 模式 vs History 模式 核心对比表

对比维度Hash 模式History 模式
URL 格式http://xxx.com/#/proOrder(带 #)http://xxx.com/proOrder(无 #)
底层原理监听 window.onhashchange 事件基于 HTML5 history.pushState/replaceState + popstate 事件
服务器请求# 后的内容不发送到服务器,仅请求 index.html完整 URL 发送到服务器,请求 /proOrder 路径
部署要求无需后端配置,直接部署即可必须配置后端(Nginx/Apache),将所有路由转发到 index.html
兼容性全浏览器兼容(IE6+)仅支持 IE10+ 及现代浏览器
SEO 友好性差(爬虫忽略 # 后内容)优(完整 URL 被收录)
锚点冲突易和页面内锚点(#top)冲突无冲突
历史记录基于浏览器哈希历史,自动记录基于 HTML5 History API,可自定义历史记录

五、实战部署:History 模式解决 404 的核心方案

部署 History 模式报 404,本质是 Nginx 未配置「路由转发」,以下是不同后端的配置方案:

1. Nginx 配置(最常用,你的场景)

server {
    listen 80;
    server_name 你的域名/服务器IP;
    root /usr/share/nginx/html/你的项目dist目录; # 项目打包后的根目录
    index index.html index.htm;
    # 核心:所有请求转发到 index.html,由前端路由接管
    location / {
        try_files $uri $uri/ /index.html; # 先找物理文件→找不到就转发到index.html
        add_header Cache-Control "no-cache, no-store, must-revalidate"; # 避免缓存
    }
    # 静态资源缓存(可选,提升加载速度)
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 7d;
        add_header Cache-Control "public, max-age=604800";
    }
}

2. Apache 配置

修改 .htaccess 文件(放在项目根目录):

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>

3. Node.js Express 配置

const express = require('express');
const path = require('path');
const app = express();
// 静态文件目录
app.use(express.static(path.join(__dirname, 'dist')));
// 所有路由转发到 index.html
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'dist/index.html'));
});
app.listen(3000, () => {
  console.log('服务器运行在 3000 端口');
});

六、选型建议:什么时候用 Hash/History?

选 Hash 模式的场景

  1. 内部管理系统(如你的工单系统)、无需 SEO 的项目;
  2. 快速开发、无法协调后端配置服务器;
  3. 需要兼容低版本浏览器(如 IE8 及以下);
  4. 临时部署、测试环境(无需复杂配置)。

选 History 模式的场景

  1. 对外展示的官网、需要 SEO 优化的项目;
  2. 追求 URL 美观,提升用户体验;
  3. 团队能协调后端修改 Nginx/Apache 配置;
  4. 现代浏览器环境(无需兼容低版本 IE)。

七、常见问题 & 解决方案

1. History 模式刷新 404

  • 原因:服务器未配置路由转发,直接请求 /proOrder 时找不到对应文件;
  • 解决:按上文配置 Nginx/Apache,添加 try_files(Nginx)或 Rewrite 规则(Apache)。

2. Hash 模式 URL 中的 # 影响锚点

问题:页面内 <a href="#top">回到顶部</a> 会被路由拦截;

解决:Vue Router 可配置hashPrefix自定义哈希前缀(如#!):

const router = createRouter({
  history: createWebHashHistory({ hashPrefix: '!' }), // 哈希前缀改为 #!
  routes
});

此时 URL 为http://xxx.com/#!/proOrder,原生锚点#top不会冲突。

3. History 模式部署在子路径(如/vue3-app)

  • 问题:部署在 http://xxx.com/vue3-app/proOrder 时路由失效;
  • 解决:
    1. Vite 配置 base: '/vue3-app/'
    2. 路由配置 createWebHistory(import.meta.env.BASE_URL)
    3. Nginx 配置 root /usr/share/nginx/html/vue3-app; + try_files $uri $uri/ /vue3-app/index.html;

总结(核心关键点)

  1. Hash 模式:靠 # 分隔,无需后端配置,兼容性好,URL 带 #,SEO 差;
  2. History 模式:基于 HTML5 API,URL 美观,SEO 好,但需后端配置路由转发,否则 404;
  3. 选型核心:对内系统 / 快速开发用 Hash,对外网站 / 需 SEO 用 History;
  4. 你的项目(工单系统):若无需 SEO,用 Hash 模式可避免 Nginx 配置;若追求 URL 美观,按上文配置 Nginx 即可解决 404。

到此这篇关于深入理解 Vue Router 中 Hash 模式和 History 模式 的核心区别、底层原理、使用场景及部署注意事项的文章就介绍到这了,更多相关vue router hash和history区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用vue.js在页面内组件监听scroll事件的方法

    使用vue.js在页面内组件监听scroll事件的方法

    今天小编就为大家分享一篇使用vue.js在页面内组件监听scroll事件的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09
  • element-ui 文件上传修改文件名的方法示例

    element-ui 文件上传修改文件名的方法示例

    这篇文章主要介绍了element-ui 文件上传修改文件名的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • Vue完整项目构建(进阶篇)

    Vue完整项目构建(进阶篇)

    这篇文章主要介绍了Vue完整项目构建(进阶篇)的相关资料,需要的朋友可以参考下
    2018-02-02
  • vue+egg+jwt实现登录验证的示例代码

    vue+egg+jwt实现登录验证的示例代码

    这篇文章主要介绍了vue+egg+jwt实现登录验证的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05
  • Vue移动端UI库之vant安装使用教程

    Vue移动端UI库之vant安装使用教程

    Vant是一个轻量、可靠的移动端组件库,目前官方只提供了Vue2、3以及微信小程序版本,并由社区团队维护React版本和支付宝小程序版本,这篇文章主要介绍了Vue移动端UI库之vant安装使用的相关资料,需要的朋友可以参考下
    2025-09-09
  • vue使用动态组件手写Router View实现示例

    vue使用动态组件手写Router View实现示例

    这篇文章主要为大家介绍了vue使用动态组件手写RouterView实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • vue3动态组件使用详解

    vue3动态组件使用详解

    这篇文章主要介绍了vue3动态组件使用详解的相关资料,需要的朋友可以参考下
    2023-02-02
  • vue如何引入sass全局变量

    vue如何引入sass全局变量

    sass或者less都提供变量设置,在需求切换主题的项目中使用less或者sass变量,这篇文章主要介绍了vue引入sass全局变量,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • vue中监听返回键问题

    vue中监听返回键问题

    这篇文章主要介绍了解决vue中监听返回键问题,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-08-08
  • Vue3 Radio单选切换展示不同内容实现代码

    Vue3 Radio单选切换展示不同内容实现代码

    这篇文章主要介绍了Vue3 Radio单选切换展示不同内容,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07

最新评论