前言:
历史模式" 指的是 Vue Router(vue-router) 提供的一种 路由模式 ,它使用 浏览器的 HTML5 History API 来管理前端路由,让单页应用(SPA)的 URL 看起来更自然、更像是传统的多页应用,没有难看的
#(井号)。
1、vue 的主要路由模式
| 名称 | 是否使用 # | 是否需要服务器配置 | 对应的 History 对象 | 推荐使用场景 |
|--------------------|-------------|-------------------|----------------|-------------------------------------------------------|---------------------|
| 1. Hash 模式 | hash模式 | ✅ 使用(如 /#/home) | ❌ 不需要 | window.location.hash | 兼容性好,快速开发,不需要服务器配置 |
| 2. History 模式 | history模式 | ❌ 不使用(如 /home) | ✅ 需要 | HTML5 History API (pushState, replaceState) | URL 更美观,适合正式环境、生产部署 |
1.1 Hash 模式
1.1.1 定义
Hash 模式 是 Vue Router 使用 URL 中的 hash(#)部分 来管理路由的一种方式,它通过监听
window.location.hash的变化来实现前端路由的切换,无需服务器端的特殊配置,并且兼容所有的浏览器(包括 IE9)。
1.1.2 URL样式
| 路由配置 | 实际访问的 URL |
|---|---|
/(首页) |
http://localhost:3000/#/或 http://example.com/#/ |
/about |
http://localhost:3000/#/about |
/user/123 |
http://localhost:3000/#/user/123 |
URL 中包含一个
#(井号) ,#后面的部分(如/about)被称为 hash 路由hash 部分的变化不会向服务器发送请求,所以不会导致页面刷新
适合用于 单页应用(SPA)
1.1.3 如何启用
通过 createWebHashHistory()来启用 Hash 模式。
// router/index.js 或 router/index.ts
import { createRouter, createWebHashHistory } from 'vue-router'
const router = createRouter({
history: createWebHashHistory(), // ✅ 启用 Hash 模式
routes: [
{ path: '/', component: Home },
{ path: '/about', component: About },
{ path: '/user/:id', component: UserDetail }
]
})
export default router
1.1.4 工作原理
-
Vue Router 会监听浏览器 URL 中
#(hash)后面的部分 的变化,例如从#/变成#/about -
当 hash 发生变化时,不会向服务器发送请求,而是通过 JavaScript 控制显示哪个组件
-
通过
window.onhashchange或类似机制,Vue Router 能够响应路由变化并渲染对应的页面内容
1.1.5 Hash 模式的特点总结
| 特性 | 说明 |
|---|---|
| ✅ URL 示例 | http://example.com/#/about |
| ✅ 是否需要服务器配置 | ❌ 不需要(推荐用于静态托管、快速开发) |
| ✅ 兼容性 | ✅ 支持所有浏览器,包括 IE9 及更早版本 |
| ✅ 是否美观 | ❌ URL 中有 #,不够简洁(但功能完整) |
| ✅ 是否支持前端路由 | ✅ 完全支持,无刷新切换页面 |
| ✅ SEO 友好性 | ❌ 不友好(搜索引擎通常忽略 #后面的内容) |
| ✅ 适用场景 | 本地开发、快速原型、静态网站、兼容旧浏览器 |
1.2 Memory 模式
1.2.1 定义
Memory 模式不会假定自己处于浏览器环境,因此不会与 URL 交互也不会自动触发初始导航 。这使得它非常适合 Node 环境和 SSR。它是用
createMemoryHistory()创建的,并且需要你在调用app.use(router)之后手动 push 到初始导航。
1.2.2 URL样式
重要:Memory 模式下,没有真实的 URL 变化!
它 不会修改浏览器地址栏
它 不会使用
#(hash)它 不会产生可被收藏或分享的真实路径
它的"路由"完全运行在 JavaScript 内存中
1.2.3 如何启用
import { createRouter, createMemoryHistory } from 'vue-router'
const router = createRouter({
history: createMemoryHistory(),
routes: [
//...
],
})
Memory 模式不会自动触发初始导航(即不会根据当前"假想"的 URL 自动跳转页面)
你需要在调用
app.use(router)挂载路由后,手动调用router.push('/')或其他路径,来初始化当前路由状态它没有浏览器历史记录,因此用户无法使用前进 / 后退按钮导航(除非你手动实现)
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
// 手动设置初始路由(比如跳转到首页)
router.push('/') // 必须手动触发,Memory 模式不会自动导航
app.mount('#app')
1.2.4 工作原理
createMemoryHistory()创建了一个 "内存中的 History 实现" ,它维护了一个 路由栈(history stack)和当前路由状态,类似于浏览器中的 History API,但是:
不依赖
window.history不修改真实的 URL
不触发浏览器的前进/后退行为(除非你手动模拟)
1.2.5 Memory 模式特点总结
| 特性 | 说明 | 适用场景 |
|---|---|---|
| 1. 不依赖浏览器环境 | 不使用 window.location、不操作 URL、不依赖 history.pushState |
Node.js、SSR、测试环境 |
| 2. 不修改浏览器地址栏 | URL 不会变化,用户看不到路由切换 | 后台逻辑、无 UI 路由 |
| 3. 路由信息保存在内存中 | 包括当前路径、路由栈等,都存在于内存,不持久化 | 测试、服务端、CLI 工具 |
| 4. 不会自动导航 | 需要手动调用 router.push()初始化路由状态 |
手动控制路由初始化 |
| 5. 没有内置历史记录 | 无法使用浏览器的前进 / 后退按钮(除非你手动维护栈) | 不适合需要用户导航感知的场景 |
| 6. 可用于 SSR / 测试 | 是服务端渲染和单元测试中常用的路由模式 | Jest、Vue Test Utils、Nuxt、SSR |
1.3 History 模式(HTML5 模式)
1.3.1 定义
History 模式 ,也叫 HTML5 模式 ,是 Vue Router 提供的一种不依赖 URL 中的
#(hash),而是利用浏览器原生history.pushStateAPI 来管理前端路由 的模式。它让前端路由的 URL 看起来和传统多页应用(MPA)一样干净、专业(没有#),但需要服务器端做相应的配置支持,否则直接访问子路由可能导致 404。
1.3.2 URL样式
| 功能 | Hash 模式 URL | History 模式 URL |
|---|---|---|
| 首页 | http://example.com/#/ |
http://example.com/ |
| 关于页 | http://example.com/#/about |
http://example.com/about |
| 用户详情 | http://example.com/#/user/123 |
http://example.com/user/123 |
没有
#,URL 更加简洁、专业,和传统网站一致看起来就像是一个普通的多页网站,但实际上是由前端路由控制的单页应用(SPA)
但必须由服务器正确配置,否则用户刷新页面或直接访问子路由(如
/about)时,服务器可能返回 404
1.3.3 如何启用
使用 createWebHistory()来启用 HTML5 / History 模式:
// router/index.js 或 router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(), // ✅ 启用 HTML5 / History 模式
routes: [
{ path: '/', component: Home },
{ path: '/about', component: About },
{ path: '/user/:id', component: UserDetail }
]
})
export default router
注意:
History 模式不会自动处理 404 页面的服务器响应,你需要确保:
服务器(如 Nginx、Apache、Netlify、Vercel 等)将 所有路由请求都重定向或返回
index.html否则,当用户直接访问
/about或刷新页面时,服务器可能找不到对应文件,返回 404 错误
1.3.4 工作原理
核心机制:利用浏览器的 History API
Vue Router 的 History 模式 基于以下浏览器提供的 API:
history.pushState(state, title, url):无刷新地添加一条新的历史记录,并更新地址栏 URL
history.replaceState(state, title, url):替换当前历史记录,不新增记录
popstate事件:当用户点击浏览器的前进/后退按钮时触发
工作流程简述:
-
初始化:
-
Vue Router 通过 **
createWebHistory()**创建一个 基于 HTML5 History API 的路由实例 -
路由匹配规则由你定义(如
/,/about,/user/:id)
-
-
导航(如点击
<router-link>或调用router.push('/about')):-
Vue Router 使用
history.pushState()更新 URL ,不会刷新页面 -
同时根据路由规则,渲染对应的组件
-
-
浏览器前进 / 后退:
-
用户点击前进/后退时,触发
popstate事件 -
Vue Router 监听到该事件,解析当前 URL,匹配对应路由,渲染相应组件
-
-
直接访问或刷新页面(如输入
/about后回车):-
浏览器会向服务器请求
/about这个路径 -
如果服务器没有配置返回 index.html,就会返回 404
-
正确配置后,服务器返回 index.html,然后 Vue Router 根据 URL 渲染对应页面
-
1.3.5 HTML5 模式特点总结
| 特性 | 说明 | 适用场景 |
|---|---|---|
1. URL 无 #,更加美观专业 |
URL 如 /about,不像 Hash 模式有 #/about |
面向用户的产品、正式官网、商业项目 |
| 2. 基于浏览器 History API | 使用 pushState/ replaceState,无刷新切换路由 |
现代浏览器(IE10+) |
| 3. 需要服务器端配置支持 | 所有路由请求必须返回 index.html,否则刷新/直接访问子路由会 404 |
需要后端或部署平台配合 |
| 4. 支持浏览器前进/后退 | ✅ 支持,且体验流畅 | 用户习惯性导航 |
| 5. 兼容性 | ✅ 支持现代浏览器(IE10 及以上) | 不支持 IE9 及以下(如需兼容,请用 Hash 模式) |
| 6. SEO 友好性相对更好 | 搜索引擎爬虫更容易抓取无 #的 URL(但仍建议搭配 SSR 更佳) |
对 SEO 有基本要求的场景 |
| 7. 不依赖 Hash,更接近传统网站 | 用户和开发者都更容易理解与接受 | 专业产品、正式发布环境 |
1.4 三种模式的对比
Vue Router 提供了三种路由模式:Hash 模式(带 #,兼容性好,无需配置)、History 模式(无 #,专业美观,但需要服务器配置)、Memory 模式(无浏览器,用于测试/SSR)。根据你的项目需求、部署环境和目标用户,选择最适合的路由模式。
| 对比维度 | Hash 模式 (createWebHashHistory()) |
History 模式 (createWebHistory()) |
Memory 模式 (createMemoryHistory()) |
|---|---|---|---|
**是否依赖 #** |
✅ 依赖(如 #/home) |
❌ 不依赖(如 /home) |
❌ 不依赖 |
| URL 是否美观 | ❌ 有 #,不够简洁专业 |
✅ 无 #,和普通网站一样 |
❌ 无 URL(内存中维护) |
| 是否需要服务器配置 | ❌ 不需要 | ✅ 必须配置(所有路由返回 index.html) | ❌ 不需要 |
| 兼容性 | ✅ 所有浏览器,包括 IE9+ | ✅ 现代浏览器(IE10+) | ✅ 无浏览器限制(用于非浏览器环境) |
| 是否支持前进/后退 | ✅ 支持(hashchange 事件) | ✅ 支持(popstate 事件) | ✅ 支持(内存维护) |
| 能否直接部署在静态托管上 | ✅ 可以(如 GitHub Pages) | ❌ 通常不行(需服务器支持) | ✅ 可以(但一般不用) |
| SEO 友好性 | ❌ 不友好(搜索引擎忽略 #后内容) |
⚠️ 相对较好(但仍建议 SSR) | ❌ 无 URL,不涉及 SEO |
| 典型使用场景 | 静态网站、原型、兼容旧浏览器、快速开发 | 正式产品、商业网站、美观 URL、可配服务器 | 测试、SSR、无浏览器环境、命令行工具等 |
| 推荐程度 | ⭐⭐⭐(适合简单项目、静态托管) | ⭐⭐⭐⭐(推荐用于正式线上项目) | ⭐(特殊用途,一般开发者很少直接使用) |
2、常见服务器的配置方法
2.1 Nginx 服务器配置
适用于:部署在 Linux 服务器、VPS、Docker 容器等环境
server {
listen 80;
server_name yourdomain.com;
root /path/to/your/dist; # Vue 打包后的文件夹,通常是 dist
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
try_files $uri $uri/ /index.html;表示:如果请求的路径不是真实文件或目录,就返回 index.html,让前端路由处理。
2.2 Apache 服务器配置
适用于:传统 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>
当请求的不是真实文件(-f)或目录(-d)时,重写到 /index.html,保 Apache 已启用 mod_rewrite模块。
2.3 Node.js 服务器(如 Express)配置示例
如果你是自己用 Node.js 搭的服务,可以这样配置:
const express = require('express')
const path = require('path')
const app = express()
// 静态文件托管(Vue 打包后的 dist 目录)
app.use(express.static(path.join(__dirname, 'dist')))
// 所有路由都返回 index.html,由 Vue Router 接管
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist', 'index.html'))
})
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000')
})
2.4 Vercel 平台配置
Vercel 是一个流行的前端静态站点托管平台,支持 SPA。
方法一:自动支持(通常可以)
Vercel 对单页应用有默认支持,但如果你遇到刷新 404,可以手动配置:
方法二:使用 vercel.json
创建 vercel.json文件,内容如下:
{
"rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
}
这会确保所有路径都返回 index.html,由 Vue 接管路由。
2.5 Netlify 平台配置
Netlify 也支持 SPA,默认情况下可能已经可以工作,但如果遇到刷新 404,可以:
方法一:使用 _redirects文件
在项目根目录(或打包后的 dist目录)创建一个名为 _redirects的文件,内容为:
/* /index.html 200
方法二:使用 netlify.toml
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
2.6 注意
这有一个注意事项。你的服务器将不再报告 404 错误,因为现在所有未找到的路径都会显示你的 index.html 文件。为了解决这个问题,你应该在你的 Vue 应用程序中实现一个万能的路由来显示 404 页面。
const router = createRouter({
history: createWebHistory(),
routes: [{ path: '/:pathMatch(.*)', component: NotFoundComponent }],
})
另外,如果你使用的是 Node.js 服务器,你可以通过在服务器端使用路由器来匹配传入的 URL,如果没有匹配到路由,则用 404 来响应,从而实现回退。查看 Vue 服务器端渲染文档了解更多信息。