Skip to content

不同的历史模式

在创建路由器实例时,history 配置允许我们在不同的历史模式中进行选择。

Hash 模式

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

const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    //...
  ],
})

它在内部传递的实际 URL 之前使用了一个井号(#)。由于这部分 URL 从未被发送到服务器,所以它不需要在服务器层面上进行任何特殊处理。不过,它在 SEO 中确实有不好的影响。如果你担心这个问题,可以使用 HTML5 模式。

Memory 模式

Memory 模式不会假定自己处于浏览器环境,因此不会与 URL 交互也不会自动触发初始导航。这使得它非常适合 Node 环境和 SSR。它是用 createMemoryHistory() 创建的,并且需要你在调用 app.use(router) 之后手动 push 到初始导航。

js
import { createRouter, createMemoryHistory } from 'vue-router'
const router = createRouter({
  history: createMemoryHistory(),
  routes: [
    //...
  ],
})

虽然不推荐,你仍可以在浏览器应用程序中使用此模式,但请注意它不会有历史记录,这意味着你无法后退或前进。

HTML5 格式

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

const router = createRouter({
  history: createWebHistory(),
  routes: [
    //...
  ],
})

使用这种模式时,URL看起来会像 https://example.com/user/id

不过,问题来了。由于我们的应用是一个单页的客户端应用,如果没有适当的服务器配置,用户在浏览器中直接访问 https://example.com/user/id,就会得到一个 404 错误

服务器配置示例

以下示例假定你正在从根目录提供服务。如果你部署到子目录,你应该使用Vue CLI 的 publicPath 配置和相关的路由器的 base 属性。你还需要调整下面的例子,以使用子目录而不是根目录(例如,将RewriteBase/ 替换为 RewriteBase/name-of-your-subfolder/)。

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

配置解析

  • location /:匹配所有请求路径

  • try_files :按顺序尝试查找文件

    • $uri:先尝试直接访问请求的静态文件(如 /css/app.css)
    • $uri/:再尝试访问目录(如请求是 /about/ 时)
    • /index.html:前两者都失败时,最后返回 index.html

与VueRouter的配合

  • 正常访问流程
    • 用户访问 https://example.com → Nginx 返回 index.html → Vue 应用启动
    • 点击路由跳转到 /about → 由 Vue Router 在客户端处理,不请求服务器
  • 刷新/直接访问子路由
    • 用户直接访问 https://example.com/about 或刷新页面时:
    • 浏览器会向服务器请求 /about
    • 如果没有这个配置,Nginx 会返回 404(因为服务器没有 /about 这个真实文件)
    • 有这个配置时,Nginx 最终会返回 index.html
    • Vue 应用启动后,Vue Router 会解析 URL 中的 /about 并渲染对应组件

附加说明

服务器如此配置以后,在匹配不到页面时或放回 index.html ,也就是说不会再报 404 了,因此应该在Vue程序中实现一个万能路由来显示 404

js
const router = createRouter({
  history: createWebHistory(),
  routes: [{ path: '/:pathMatch(.*)', component: NotFoundComponent }],
})