Vue-Router 路由模式原理
Hash 和 History 两种路由模式的实现原理与区别
问题
Vue-Router 提供了 Hash 和 History 两种路由模式,它们的实现原理是什么?有什么区别?
解答
Hash 模式
Hash 模式利用 URL 中的 # 部分,通过监听 hashchange 事件实现路由切换。
// Hash 路由简易实现
class HashRouter {
constructor() {
this.routes = {}
// 监听 hash 变化
window.addEventListener('hashchange', this.onHashChange.bind(this))
// 页面加载时也要处理
window.addEventListener('load', this.onHashChange.bind(this))
}
// 注册路由
route(path, callback) {
this.routes[path] = callback
}
// hash 变化时触发
onHashChange() {
// 获取 # 后面的路径,默认 '/'
const hash = window.location.hash.slice(1) || '/'
const callback = this.routes[hash]
if (callback) {
callback()
}
}
// 跳转路由
push(path) {
window.location.hash = path
}
}
// 使用示例
const router = new HashRouter()
router.route('/', () => {
console.log('首页')
})
router.route('/about', () => {
console.log('关于页')
})
// 跳转
router.push('/about') // URL 变为 http://example.com/#/about
History 模式
History 模式使用 HTML5 的 History API,通过 pushState 和 popstate 事件实现。
// History 路由简易实现
class HistoryRouter {
constructor() {
this.routes = {}
// 监听浏览器前进后退
window.addEventListener('popstate', this.onPopState.bind(this))
}
// 注册路由
route(path, callback) {
this.routes[path] = callback
}
// popstate 触发时(前进/后退)
onPopState() {
const path = window.location.pathname
const callback = this.routes[path]
if (callback) {
callback()
}
}
// 跳转路由
push(path) {
// 修改 URL,不刷新页面
window.history.pushState({}, '', path)
// pushState 不会触发 popstate,需要手动执行回调
const callback = this.routes[path]
if (callback) {
callback()
}
}
// 替换当前路由
replace(path) {
window.history.replaceState({}, '', path)
const callback = this.routes[path]
if (callback) {
callback()
}
}
}
// 使用示例
const router = new HistoryRouter()
router.route('/', () => {
console.log('首页')
})
router.route('/about', () => {
console.log('关于页')
})
// 跳转
router.push('/about') // URL 变为 http://example.com/about
两种模式对比
| 特性 | Hash 模式 | History 模式 |
|---|---|---|
| URL 形式 | /#/path | /path |
| 服务器配置 | 不需要 | 需要配置回退 |
| SEO | 不友好 | 友好 |
| 兼容性 | IE8+ | IE10+ |
| 原理 | hashchange 事件 | History API |
History 模式服务器配置
History 模式需要服务器支持,否则刷新页面会 404。
# Nginx 配置
location / {
try_files $uri $uri/ /index.html;
}
// Node.js Express 配置
const express = require('express')
const history = require('connect-history-api-fallback')
const app = express()
app.use(history())
app.use(express.static('dist'))
Vue-Router 配置
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
// History 模式
const router = createRouter({
history: createWebHistory(),
routes: [...]
})
// Hash 模式
const router = createRouter({
history: createWebHashHistory(),
routes: [...]
})
关键点
- Hash 模式通过
hashchange事件监听#后的变化,兼容性好,无需服务器配置 - History 模式使用
pushState/replaceState修改 URL,popstate监听前进后退 pushState不会触发popstate,只有浏览器前进后退才会触发- History 模式需要服务器配置,将所有路由请求回退到
index.html - Hash 变化不会发送请求到服务器,History 模式的 URL 会
目录