探索Hash Router:构建单页应用的基石
前言
第一次看到Vue的路由模式的时候,有点分不清楚 createWebHashHistory()
和 createWebHistory
的区别,感觉功能也差不多。后来去搜了一下发现前面的那个叫做哈希模式,哈希模式通过URL的hash(即#后面的部分)来实现前端路由。我寻思着好像我在html里面见过这东东,找了找遗失的记忆,果然存在。和我们用来浏览器定位的锚链接相同,点击锚链接也同样会发生地址的改变,但是页面不会进行刷新。因此我查阅了一下资料。咦,原来这种使用hash路由不进行页面刷新的应用叫做SPA单页应用。
传统的HTTP协议是无状态的,这意味着服务器端在完成一次请求响应后,并不能主动向客户端推送内容,每次请求新的资源,如从/page1跳转到/page2,都需要浏览器重新发送请求,服务器返回完整的HTML文档。这不仅增加了网络负担,也让用户在等待页面加载时体验不佳。
而单页应用的出现,彻底改变了这一现状。通过前端路由技术,如Hash Router,我们能够在不重新加载整个页面的情况下,实现页面内容的动态替换,仅仅通过修改URL的哈希值(即URL中#后面的部分),就能模拟页面跳转,从而实现无刷新的页面过渡,极大地提升了用户体验。
Hash Router的工作原理
Hash Router的核心在于监听URL的哈希值变化,即hashchange
事件。这个事件是浏览器原生的JS事件,无论是否使用 Vue.js 或其他框架。当浏览器的 URL 的 hash(即 URL 中 #
后面的部分)发生变化时,会触发 hashchange
事件。当用户点击链接或通过JavaScript操作改变URL的哈希部分时,浏览器会触发此事件,而不会重新加载页面。Hash Router利用这一特性,根据不同的哈希值加载相应的组件或视图,更新页面内容。我们可以进行自己的手写一个简单的基于哈希(hash)的路由系统,来实现一下hash 路由的使用。
路由系统实现
HTML结构
<nav id="nav">
<ul>
<li><a href="#/page1">page1</a></li>
<li><a href="#/page2">page2</a></li>
<li><a href="#/page3">page3</a></li>
</ul>
</nav>
<div id="container"></div>
这里定义了一个导航菜单,包含三个链接,分别指向不同的哈希路径(#/page1
, #/page2
, #/page3
)。<div id="container">
作为内容展示区域,将根据路由变化动态更新其内容。大家可以先创建一个html将内容复制然后点击查看一下url路径的改变和页面有无进行刷新
HashRouter 类进行路由管理
class HashRouter {
constructor() {
this.routes = {};//page => Component
// window.addEventListener('hashChange', this.load.bind(this), false)
window.addEventListener('hashchange', () => {
this.load();
}, false)
}
register(hash, callback = function () { }) {
this.routes[hash] = callback;
}
registerIndex(callback = function () { }) {
this.routes['index'] = callback;
}
load() {
console.log(location.hash);
let hash = location.hash.slice(1);//去掉# 方是路由
console.log(hash);
if (!hash) {
//首页
this.routes['index'] && this.routes['index'].call(this);
} else {
//相应页面
this.routes[hash] && this.routes[hash].call(this);
}
}
}
- 构造函数:初始化路由对象,并监听
hashchange
事件,当哈希值改变时,调用load
方法。 - register方法:允许用户注册一个哈希路径和对应的处理函数。
- registerIndex方法:特化处理首页逻辑,确保没有哈希时显示首页。
- load方法:根据当前哈希值查找路由表,执行相应的处理函数,更新页面内容。
这里进行路由加载的时候需要特别注意需要先进行路由是否注册的判断,因为用户可能进行非法输入,但是你没有相对的路由注册,那么就会报错。所以这里我们先进行路由检查在进行路由相对应的处理函数。
路由注册与初始化
let router = new HashRouter();
router.registerIndex(() => container.innerHTML = `<h1>首页</h1>`);
router.register('/page1', () => container.innerHTML = `<h1>page1</h1>`);
router.register('/page2', function () {
console.log(this, this.routes);
container.innerHTML = `<h1>page2</h1>`;
});
router.register('/page3', () => container.innerHTML = `<h1>page3</h1>`);
console.log(router.routes);
router.load();
- 创建实例:创建
HashRouter
的实例router
。 - 注册路由:分别注册了首页和其他页面的路由处理逻辑,当路由被命中时,会将
container
的innerHTML
替换为对应页面的内容。 - 初始化加载:手动调用
router.load()
进行首次页面加载,展示当前哈希对应的页面内容。
初始化加载主要是进行路由分享进来的用户可以直接定位当前路由展示的页面组件
总结
这段代码通过定义一个简单的HashRouter
类,实现了基本的单页应用路由功能。当用户点击导航链接改变URL哈希时,会触发页面内容的无刷新更新。通过直接操作DOM(即container.innerHTML
)来展示不同页面,是早期SPA开发的一种常见模式,虽然简单但直观展示了SPA路由的核心原理。随着框架如Vue Router的发展,现代SPA应用更多采用组件化的路由管理,但理解这段基础逻辑对于深入学习前端路由机制非常有帮助。
本次文章就分享到这里了,喜欢的话就点个关注和赞吧- ̗̀(๑ᵔ⌔ᵔ๑)。
转载自:https://juejin.cn/post/7389621546257547301