切换语言为:繁体

哈希路由在 SPA 中的妙用,以提高了应用的性能和用户体验。

  • 爱糖宝
  • 2024-07-11
  • 2066
  • 0
  • 0

前言

单页应用(Single Page Application,简称SPA)的设计模式在现代Web开发中变得越来越流行,主要因为它能提供类似桌面应用的用户体验。SPA通过动态加载和替换部分网页内容,而无需重新加载整个页面,这带来了快速响应和流畅的交互效果。然而,这种模式对传统的HTTP协议提出了挑战,因为HTTP本质上是无状态的,且服务器无法主动向客户端推送内容。因此,SPA需要一些技术来管理状态并实现页面的动态更新。

正文

使用Hash Router进行管理

在单页应用中,一个常见的解决方案是使用“Hash Router”。Hash Router利用URL中的hash(#)部分来区分不同的页面或视图。当用户在浏览器地址栏中修改URL的hash部分时,浏览器会触发hashchange事件。开发者可以监听这个事件,并通过异步请求(如AJAX)从服务器获取数据,然后更新DOM以显示相应的视图。

有许多小白可能不懂什么意思

简单来说,在传统的多面应用中,每个页面都有独特的URL,例如我们从掘金首页

哈希路由在 SPA 中的妙用,以提高了应用的性能和用户体验。 

此时的URL为https://juejin.cn/,而如果我们进入某一篇文章时,整个页面会重新加载并刷新

哈希路由在 SPA 中的妙用,以提高了应用的性能和用户体验。

URL也会随之改变,使得页面会重新加载

URL的改变意味着浏览器需要重新向对应服务器发送请求,十分耗费服务器资源

但是在单页面应用当中,页面的主要内容不会重新加载,而是通过JavaScript动态地替换部分内容,从而提供了更快的响应速度和更流畅的用户体验。

这个哈希路由就是一个锚点

举个例子!

在某篇文章中,其右边的目录就运用了哈希路由

哈希路由在 SPA 中的妙用,以提高了应用的性能和用户体验。

例如我们点击它的结语,页面就会跳到这个部分,

哈希路由在 SPA 中的妙用,以提高了应用的性能和用户体验。

并且URL改变为

哈希路由在 SPA 中的妙用,以提高了应用的性能和用户体验。

其URL内的Hash字段则会修改,Hash字段就是URL中带#后的内容

修改后,页面并不加载,而是跳转到定义的锚点,这个锚点就是哈希路由,而在这个URL中,它的结语的哈希路由为heading-5

现在你明白什么是哈希路由(Hash Router)了吗

我们现在就来探究一下,这样一个锚点是如何实现的

先设置三个导航栏
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>手写Hash Router</title>
</head>
<body>
    <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>
    </nav>
    <div id="container"></div>
</body>
</html>

我们使用<a>标签来分别指向三个页面的URL,#就代表着URL的哈希字段,点击这三个标签就会分别跳转这三个锚点。

还定义了一个container,用来放显示的界面,就像Vue中的<router-view>

接下来我们通过JS来实现——锚点时空跳跃

也就是说,当我们跳转至#/page1时,page1就要放进container中

我们跳转至#/page1时,page1就要放进container中

开始动手!

我们先定义一个实现路由类:

class HashRouter{}

再写一个构造函数,定义一个变量routes来保存路由规则,再添加一个事件监听,监听hashchange事件,一旦hash值改变,就调用load方法。

 constructor() {
        this.routes = {}; // 创建一个对象来存储路由规则
        window.addEventListener('hashchange', this.load.bind(this), false); // 当URL的hash部分发生变化时,调用load方法
    }

我们再写两个函数,将各页面导入进HTML的方法使用routes对象通过数组绑定,也就是注册路由规则

 register (hash, callback = function() {}) {
        this.routes[hash] = callback; // 注册路由规则,将hash和对应的回调函数存储在routes对象中
    }
    registerIndex(callback = function() {}) {
        this.routes['index'] = callback; // 注册默认路由,当hash为空时使用
    }

接下来我们来写load方法,

先从location.hash获取当前URL的哈希部分。由于哈希总是以#开始,所以使用slice(1)来去除这个字符,得到实际的哈希值字符串。

再根据hash的值,load方法会从this.routes对象中查找对应的处理器。如果hash为空,意味着URL中没有特定的哈希值,这时会使用默认的index处理器,即通过registerIndex方法注册的回调函数。如果hash有值,它会尝试作为键在routes对象中查找对应的处理器。

简单来说,如果URL中有hash字段则调用该页面的方法使该页面展示,如果没有就展示首页

load() {
        let hash = location.hash.slice(1); // 去掉hash前缀'#",获取当前hash值
        let handler;
        if(!hash) {
            // 如果hash为空,则使用默认路由
            handler = this.routes['index'];
        } else {
            // 否则根据hash值找到对应的handler
            handler = this.routes[hash];
        }
        handler && handler.call(this); // 执行找到的handler,如果没有找到则不执行任何操作
    }

最后我们创建一个实例对象,再获取container元素

let router = new HashRouter(); // 创建一个HashRouter实例
let container = document.getElementById('container'); // 获取页面上的容器元素

我们将三个页面事件和首页与实例对象内的routes对象进行路由规则注册

// 注册不同的路由规则
router.registerIndex(() => container.innerHTML = '我是首页');
router.register('/page1', () => container.innerHTML = '我是Page1');
router.register('/page2', () => container.innerHTML = '我是Page2');
router.register('/page3', () => container.innerHTML = '我是Page3');

最后加载路由规则

router.load(); // 加载当前的路由规则

于是我们的手写哈希路由就完成了

哈希路由在 SPA 中的妙用,以提高了应用的性能和用户体验。

点击page1 哈希路由在 SPA 中的妙用,以提高了应用的性能和用户体验。

完整js代码

 
class HashRouter{
    constructor() {
        this.routes = {}; // 创建一个对象来存储路由规则
        window.addEventListener('hashchange', this.load.bind(this), false); // 当URL的hash部分发生变化时,调用load方法
    }
    register (hash, callback = function() {}) {
        this.routes[hash] = callback; // 注册路由规则,将hash和对应的回调函数存储在routes对象中
    }
    registerIndex(callback = function() {}) {
        this.routes['index'] = callback; // 注册默认路由,当hash为空时使用
    }
    load() {
        let hash = location.hash.slice(1); // 去掉hash前缀'#",获取当前hash值
        let handler;
        if(!hash) {
            // 如果hash为空,则使用默认路由
            handler = this.routes['index'];
        } else {
            // 否则根据hash值找到对应的handler
            handler = this.routes[hash];
        }
        handler && handler.call(this); // 执行找到的handler,如果没有找到则不执行任何操作
    }
}

let router = new HashRouter(); // 创建一个HashRouter实例
let container = document.getElementById('container'); // 获取页面上的容器元素

// 注册不同的路由规则
router.registerIndex(() => container.innerHTML = '我是首页');
router.register('/page1', () => container.innerHTML = '我是Page1');
router.register('/page2', () => container.innerHTML = '我是Page2');
router.register('/page3', () => container.innerHTML = '我是Page3');

router.load(); // 加载当前的路由规则

总结

哈希路由是一种实用的技术,它使得SPA能够在不重新加载整个页面的情况下实现页面内容的动态更新,从而提高了应用的性能和用户体验。

0条评论

您的电子邮件等信息不会被公开,以下所有项均必填

OK! You can skip this field.