Vue Router 的两种模式区别以及使用注意事项
Category(分类): Vue Status: 已核对
Vue Router 与 Vue 深度集成,常见浏览器 URL 策略是 hash 与 HTML5 history。需要先区分版本:Vue Router 3(通常配合 Vue 2)默认 mode: 'hash';Vue Router 4(配合 Vue 3)不再使用 mode 字符串,创建路由时必须显式选择 history 实现。
Vue Router 3 写法(历史版本)
原文示例属于 Vue Router 3:
const router = new VueRouter({
mode: 'history', // 也可以是 'hash'
base: '/',
routes: []
})
这段内容仍可用于维护 Vue 2 / Router 3 项目,但不能直接复制到 Router 4。
hash 模式
浏览器原生修改 location.hash 通常会触发 hashchange,URL 的 fragment(# 后内容)不会发送给服务器:
window.addEventListener('hashchange', (event) => {
console.log(event.oldURL, event.newURL)
})
因此直接访问 https://example.com/#/users/1 时,服务器通常只收到 /,不需要为 #/users/1 配置回退。代价是 URL 带 #,SEO 与服务端按路径识别页面的能力较弱。
不过,“Vue Router 的 hash 模式完全依赖 hashchange”是过度简化。Router 3 在支持 History API 的浏览器中,HashHistory 会使用 pushState / replaceState 并监听 popstate,只在不支持时回退到 hashchange;Router 4 的 createWebHashHistory() 也复用 HTML5 history 实现。上面的原生实验只能说明浏览器 hash 行为,不能代表每个 Router 版本的内部实现。
history 模式与浏览器 API
HTML5 History API 的关键能力包括:
history.pushState(data, title, url):增加一个历史条目。history.replaceState(data, title, url):替换当前历史条目。history.state:读取当前条目的状态。popstate:历史条目被激活时触发,常见于用户前进/后退或go()、back()、forward()。
直接调用 pushState() 或 replaceState() 不会触发 popstate。 Router 主动导航时会调用 push/replace 并立即处理导航,同时监听 popstate 处理浏览器历史遍历:
window.addEventListener('popstate', (event) => {
console.log('历史遍历后的状态:', event.state)
})
history.pushState({ page: 1 }, '', '/page/1') // 不触发 popstate
history.replaceState({ page: 2 }, '', '/page/2') // 不触发 popstate
history URL 更像普通地址,例如 https://example.com/users/1,但刷新或直接访问时浏览器会向服务器请求 /users/1,因此必须配置服务端支持。
Vue Router 4 当前写法
import {
createRouter,
createWebHashHistory,
createWebHistory
} from 'vue-router'
const router = createRouter({
history: createWebHistory(),
// 无法配置服务器 fallback 时可改用 createWebHashHistory()
routes: []
})
export default router
入口还要安装路由:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app')
Router 4 另有 createMemoryHistory(),常用于 SSR 或 Node 环境。
history 模式的服务器 fallback
静态 SPA 的服务器应只在请求不是实际文件、目录或 API时回退到 index.html。Nginx 常见配置:
location /api/ {
try_files $uri =404;
}
location /assets/ {
try_files $uri =404;
}
location / {
try_files $uri $uri/ /index.html;
}
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>
不能把 API、JavaScript、CSS、图片等失败请求无条件回退成 HTML,否则客户端可能以错误的 MIME 类型解析 index.html,真正的接口或资源 404 也会被掩盖。
客户端 404 与真实 HTTP 404
服务器 fallback 只保证 SPA 能启动。未知路径如果也返回 index.html,HTTP 状态往往仍是 200;Router 的 catch-all 只能展示“未找到”组件,不等于返回真正的 HTTP 404。
Vue Router 3 的历史写法应放在路由末尾:
// Vue Router 3
{ path: '*', component: NotFound }
Vue Router 4 改用自定义参数正则:
// Vue Router 4
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: NotFound
}
若 SEO、监控或协议语义要求真实 HTTP 404,需要服务器或 SSR 入口先匹配路由,再把响应状态设为 404;纯静态 fallback 通常只能得到“视觉 404”。
部署到子目录
Router base、构建工具的静态资源 base 和服务器 rewrite 必须一致:
// Router 3
new VueRouter({ mode: 'history', base: '/docs/', routes })
// Router 4
createRouter({
history: createWebHistory('/docs/'),
routes
})
hash 模式也可传 base:createWebHashHistory('/docs/')。部署前应实际验证直接访问、刷新、前进后退、静态资源、API 和未知路由。
如何选择
| 条件 | 建议 |
|---|---|
| 能配置服务器/CDN fallback,重视自然 URL | createWebHistory() |
| 纯静态托管且无法配置回退 | createWebHashHistory() |
| SSR / Node 或测试环境 | createMemoryHistory() |
| 维护 Vue 2 老项目 | 保留 Router 3 mode 写法并明确版本 |