Hash 路由原理
前端路由 Hash 模式的实现原理与代码示例
问题
解释前端路由中 Hash 模式的工作原理,并实现一个简单的 Hash 路由。
解答
Hash 模式基础
Hash 模式利用 URL 中 # 后面的部分(hash 值)来实现前端路由。hash 值的变化不会触发页面刷新,也不会向服务器发送请求。
https://example.com/#/home
↑
hash 部分
核心 API
// 获取当前 hash 值
window.location.hash // '#/home'
// 设置 hash 值
window.location.hash = '#/about'
// 监听 hash 变化
window.addEventListener('hashchange', (e) => {
console.log('旧 URL:', e.oldURL)
console.log('新 URL:', e.newURL)
console.log('当前 hash:', location.hash)
})
实现简易 Hash 路由
class HashRouter {
constructor() {
// 存储路由与回调的映射
this.routes = {}
// 绑定 hashchange 事件
window.addEventListener('hashchange', this.onHashChange.bind(this))
// 页面加载时也要处理当前 hash
window.addEventListener('load', this.onHashChange.bind(this))
}
// 注册路由
route(path, callback) {
this.routes[path] = callback
}
// hash 变化时的处理函数
onHashChange() {
// 获取当前 hash,去掉 # 号
const hash = location.hash.slice(1) || '/'
// 执行对应的回调
const callback = this.routes[hash]
if (callback) {
callback()
}
}
// 跳转到指定路由
push(path) {
location.hash = path
}
}
// 使用示例
const router = new HashRouter()
router.route('/', () => {
console.log('首页')
document.body.innerHTML = '<h1>首页</h1>'
})
router.route('/about', () => {
console.log('关于页')
document.body.innerHTML = '<h1>关于页</h1>'
})
router.route('/user', () => {
console.log('用户页')
document.body.innerHTML = '<h1>用户页</h1>'
})
// 导航
router.push('/about')
完整 HTML 示例
<!DOCTYPE html>
<html>
<head>
<title>Hash Router Demo</title>
</head>
<body>
<nav>
<a href="#/">首页</a>
<a href="#/about">关于</a>
<a href="#/user">用户</a>
</nav>
<div id="app"></div>
<script>
class HashRouter {
constructor() {
this.routes = {}
window.addEventListener('hashchange', this.onHashChange.bind(this))
window.addEventListener('load', this.onHashChange.bind(this))
}
route(path, callback) {
this.routes[path] = callback
}
onHashChange() {
const hash = location.hash.slice(1) || '/'
const callback = this.routes[hash]
if (callback) callback()
}
}
const router = new HashRouter()
const app = document.getElementById('app')
router.route('/', () => {
app.innerHTML = '<h1>首页内容</h1>'
})
router.route('/about', () => {
app.innerHTML = '<h1>关于我们</h1>'
})
router.route('/user', () => {
app.innerHTML = '<h1>用户中心</h1>'
})
</script>
</body>
</html>
Hash 模式 vs History 模式
| 特性 | Hash 模式 | History 模式 |
|---|---|---|
| URL 形式 | /#/path | /path |
| 服务器配置 | 不需要 | 需要配置回退 |
| 兼容性 | IE8+ | IE10+ |
| SEO | 较差 | 较好 |
关键点
- hash 变化不会刷新页面,不会发送请求到服务器
- 通过
hashchange事件监听 hash 变化 location.hash获取和设置 hash 值- Hash 模式兼容性好,无需服务器配置
- hash 值不会被包含在 HTTP 请求中
目录