深入理解 Vue Router 中 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 事件,前端可在该事件中判断哈希值,渲染对应组件:

javascript 复制代码
// 原生 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 模式

typescript 复制代码
// 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)路由跳转的本质
javascript 复制代码
// 原生 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 模式

typescript 复制代码
// 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 配置(最常用,你的场景)

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 文件(放在项目根目录):

apache 复制代码
<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 配置

javascript 复制代码
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自定义哈希前缀(如#!):

    typescript 复制代码
    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。
相关推荐
San303 小时前
破茧成蝶:Web 前端开发的三次革命与架构演进史
javascript·vue.js·ecmascript 6
性野喜悲4 小时前
<script setup lang=“ts“>+element-plus模拟required 展示星号*且不触发 Element UI 的校验规则
javascript·vue.js·elementui
GIS好难学4 小时前
2025年华中农业大学暑期实训优秀作品(5):智慧煤仓监控系统平台——重塑煤炭仓储管理新模式
前端·vue.js·信息可视化·gis开发·webgis
古韵5 小时前
如何从Axios平滑迁移到Alova
vue.js·react.js·node.js
WYiQIU5 小时前
突破字节前端2-1⾯试: JS异步编程问题应答范式及进阶(视频教学及完整源码笔记)
开发语言·前端·javascript·vue.js·笔记·面试·github
Knight_AL6 小时前
布隆过滤器参数深度解析:如何根据误判率计算位数组大小与哈希函数数量
算法·哈希算法
小胖霞6 小时前
从生活实例解释什么是AST抽象语法树
vue.js
华仔啊6 小时前
Vue3和Vue2的核心区别?很多开发者都没完全搞懂的10个细节
前端·vue.js
烤麻辣烫6 小时前
黑马大事件学习-15(前端登录页面)
前端·css·vue.js·学习·html