技术知识文章集合TECHNICAL ARCHIVE · 457 DOCUMENTS

显示模式

登录
ARCHIVE DOCUMENTVUE

带你了解 Vue Router 的两种路由模式

所属馆藏
Vue
文件格式
Markdown
原始路径
Vue/76-带你了解 Vue-Router 的两种路由模式
本文目录7 个章节
  1. 一、路由模式解决什么问题
  2. 二、Hash 模式
  3. 三、HTML5 History 模式
  4. 四、Hash 和 History 的对比
  5. 五、路由模式之外还要注意什么
  6. 六、总结
  7. 参考资料

带你了解 Vue Router 的两种路由模式

原文介绍 hash 和 history 两种模式,并通过浏览器 API 演示路径变化。本文保留原有示例,同时修正“history 每次切换都会请求后端”、pushState 会触发 popstate 等常见误解,并补充 Vue Router 3、4/5 和服务器部署的差异。

一、路由模式解决什么问题

前端路由的目标是:在单页应用中改变当前 URL,并根据 URL 渲染不同页面,而不必每次点击都重新下载完整 HTML。

浏览器 URL 可以粗略分为:

协议://主机/路径?查询参数#片段

其中 hash 片段由 # 开始,不会作为 HTTP 请求路径发送给服务器;pathname、query 等则会参与正常的文档请求。客户端路由器可以监听 URL 变化,再渲染对应组件。

Vue Router 常见的浏览器模式是:

  • Hash 模式:URL 中包含 #,使用 hashchange
  • HTML5 History 模式:URL 没有 #,使用 history.pushStatereplaceStatepopstate

Vue Router 4/5 还提供 memory history,主要给 SSR、Node 或非浏览器环境使用。

二、Hash 模式

1. 地址和服务器请求

Hash URL 例如:

https://example.com/#/vue

浏览器请求文档时,服务器通常只看到 /,不会收到 #/vue。因此服务器不需要为每个前端路由配置 HTML fallback,刷新时一般也不会因为前端路径不存在而返回 404。

没有配置 History fallback 时的 404 示例(已本地化)

Hash URL 可以在同一页面切换的示例(已本地化)

Hash 片段变化不会触发整页导航,但浏览器会记录 hash 历史,所以前进和后退仍然可以触发路由变化。缺点是 URL 中有 #,对 SEO、分享链接观感和某些服务端分析场景不如正常路径;现代浏览器兼容性通常不是主要问题。

2. 原生 hash 示例

<button id="hash-button">切换到 /home</button>

<script>
  const button = document.querySelector('#hash-button')

  window.addEventListener('hashchange', event => {
    console.log('old URL:', event.oldURL)
    console.log('new URL:', event.newURL)
    console.log('current hash:', window.location.hash)
    render(window.location.hash.slice(1) || '/')
  })

  button.addEventListener('click', () => {
    window.location.hash = '/home'
    // 也可以使用 location.href = '#/home'
  })

  function render(path) {
    console.log('根据 hash 渲染页面:', path)
  }
</script>

hashchange 会在 hash 改变后触发。改变其他 pathname 或 query 不会触发这个事件。真实 Vue Router 还需要负责路由匹配、参数、query、导航守卫、异步组件和 RouterView

3. Vue Router 中的配置

Vue Router 3:

const router = new VueRouter({
  mode: 'hash',
  routes,
})

Vue Router 4/5:

import { createRouter, createWebHashHistory } from 'vue-router'

const router = createRouter({
  history: createWebHashHistory(),
  routes,
})

Vue Router 3 的 mode 和 Router 4/5 的 history 是不同 API,不能混写。

三、HTML5 History 模式

1. pushState 不等于向服务器请求

History API 可以在当前页面中修改地址并建立历史记录:

history.pushState({ page: 'home' }, '', '/home')
history.replaceState({ page: 'home' }, '', '/home')

这两个方法本身不会发送 HTTP 请求,也不会自动触发 popstate。应用需要在调用后主动更新视图;当用户点击浏览器前进/后退时,浏览器才会触发 popstate

只有以下情况通常会请求服务器:

  • 用户直接打开一个深层 History URL;
  • 用户刷新页面;
  • 页面从外部导航进入该 URL;
  • 应用主动进行了整页导航。

History 模式直接访问深层路径可能得到 404(已本地化)

2. 原生 history 示例

<button id="history-button">切换到 /home</button>

<script>
  const button = document.querySelector('#history-button')

  function render(path) {
    console.log('根据 pathname 渲染页面:', path)
  }

  button.addEventListener('click', () => {
    const path = '/home'
    history.pushState({ path }, '', path)
    render(path) // pushState 不会自动触发 popstate
  })

  window.addEventListener('popstate', event => {
    console.log('popstate state:', event.state)
    render(window.location.pathname)
  })

  window.addEventListener('DOMContentLoaded', () => {
    render(window.location.pathname)
  })
</script>

初始页面的 event.state 可能是 null,因为浏览器不会自动为每一个历史条目提供应用自定义的 state。路由器应以当前 URL 为主要匹配依据,不能假设 state 一定存在。

History 模式监听路径和历史状态的示例(已本地化)

3. Vue Router 中的配置

Vue Router 4/5 推荐使用 createWebHistory()

import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    { path: '/', component: () => import('./views/HomeView.vue') },
    { path: '/home', component: () => import('./views/HomeView.vue') },
  ],
})

Vue Router 3 对应写法:

const router = new VueRouter({
  mode: 'history',
  routes,
})

History 模式 URL 更自然,也更适合服务端参与渲染和 SEO,但部署服务器必须把未知的前端路径回退到应用入口 index.html,同时让真实静态资源正常返回。

例如 nginx:

location / {
  try_files $uri $uri/ /index.html;
}

如果应用部署在子目录,需要为 router 配置正确的 base,并同步调整服务器 fallback。Nuxt 4 由框架处理文件路由、服务端渲染和部署适配时,不应直接照搬纯 Vite SPA 的 nginx 配置。

四、Hash 和 History 的对比

维度HashHTML5 History
URL包含 #正常 pathname
主要 APIhashchangepushStatereplaceStatepopstate
刷新深层路径通常不需要额外 fallback需要服务器 fallback
服务端收到 hash不会收到会收到 pathname/query
SEO/链接观感通常较弱通常更自然
部署复杂度较低需要正确配置服务器
Vue Router 4/5createWebHashHistory()createWebHistory()

没有绝对更好的模式:

  • 静态托管、无法修改服务器配置或旧系统迁移时,Hash 更省事;
  • 需要干净 URL、服务端渲染或更好的搜索引擎路径时,History 更合适;
  • SSR/Node 环境可以考虑 createMemoryHistory(),但它不会自动操作浏览器 URL,也不会自动执行初始导航,应用需要手动 push 初始地址。

五、路由模式之外还要注意什么

1. 路由导航和页面渲染

路由模式只负责 URL 历史,真正的 Vue Router 还提供:

<RouterLink to="/home">首页</RouterLink>
<RouterView />

以及动态参数、query、嵌套路由、异步组件、滚动行为和导航守卫。

2. 导航守卫版本差异

Vue Router 3 常见:

router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && !isLoggedIn()) {
    next({ name: 'login' })
    return
  }
  next()
})

Vue Router 4/5 推荐直接返回结果:

router.beforeEach(to => {
  if (to.meta.requiresAuth && !isLoggedIn()) {
    return { name: 'login', query: { redirect: to.fullPath } }
  }
  return true
})

3. 404 页面

服务器 fallback 只保证把请求交给前端应用,不代表路由一定存在。仍然需要在客户端配置 catch-all 路由:

{
  path: '/:pathMatch(.*)*',
  component: () => import('./views/NotFoundView.vue'),
}

如果服务端拥有自己的 SSR 路由匹配器,则还可以在服务端对真正不存在的 URL 返回 404。

六、总结

  • Hash 模式利用 URL 片段和 hashchange,片段不发送给服务器,部署简单;
  • History 模式利用 History API,pushState/replaceState 修改地址但不会自动触发 popstate
  • History 模式点击链接通常不会请求服务器,但刷新或直接访问深层 URL 时需要服务器 fallback;
  • Vue Router 3 使用 mode,Vue Router 4/5 使用 createWebHistory/createWebHashHistory
  • 路由模式不是安全机制,权限仍需由服务端校验;
  • 选择模式时综合考虑部署能力、SEO、SSR、URL 体验和项目历史,而不是只看有没有 #

参考资料

原文作者:东方小月。原文关于 hash/history 地址差异、浏览器 API、前进后退和服务器配置的主线予以保留;重复段落、损坏的代码围栏、编号噪声以及对 pushStatepopstate 和服务端请求的错误描述已清理或修正。

457 DOCUMENTS · 10 COLLECTIONS
ARCHIVE SEARCH457 篇文章

SEARCH GUIDE

输入关键词开始搜索

支持搜索文章标题、所属分类和原始文档路径。

按分类浏览

10 COLLECTIONS