Vue Router (历史模式)

前言:

历史模式" ​ 指的是 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事件:当用户点击浏览器的前进/后退按钮时触发

工作流程简述:

  1. 初始化:

    • Vue Router 通过 **createWebHistory()**创建一个 基于 HTML5 History API 的路由实例

    • 路由匹配规则由你定义(如 /, /about, /user/:id

  2. 导航(如点击 <router-link>或调用 router.push('/about')):

    • Vue Router 使用 history.pushState()更新 URL不会刷新页面

    • 同时根据路由规则,渲染对应的组件

  3. 浏览器前进 / 后退:

    • 用户点击前进/后退时,触发 popstate事件

    • Vue Router 监听到该事件,解析当前 URL,匹配对应路由,渲染相应组件

  4. 直接访问或刷新页面(如输入 /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 服务器端渲染文档了解更多信息。

相关推荐
是梦终空2 小时前
vue下载依赖报错npm ERR node-sass@4.14.1 postinstall: `node scripts/build.js`的解决方法
javascript·npm·vue·node-sass·vue依赖
依米_2 小时前
一文带你剖析 Promise.then all 实现原理,状态机、发布订阅模式完美实现异步编程
javascript·设计模式
陈陈小白2 小时前
npm run dev报错Error: listen EADDRINUSE: address already in use :::8090
前端·npm·node.js·vue
G018_star sky♬2 小时前
使用npm运行js脚本覆盖vue依赖包
javascript·vue.js
杂鱼豆腐人2 小时前
pnpm环境下防止误使用npm的方法
前端·git·npm·node.js·git bash
我是ed2 小时前
# vue2 使用 cesium 展示 TLE 星历数据
前端
宇余2 小时前
从 useState 到 URLState:前端状态管理的另一种思路
前端·vue.js
白兰地空瓶2 小时前
🚀 10 分钟吃透 CSS position 定位!从底层原理到避坑实战,搞定所有布局难题
前端·css