likes
comments
collection
share

实现一个简单的哈希路由系统(Hash Router):单页应用中的URL管理与页面切换

作者站长头像
站长
· 阅读数 19

前言

在Web开发中,单页应用(Single Page Application, SPA)通过动态加载和更新内容,为用户提供了流畅且类似原生应用的体验。然而,由于HTTP协议的无状态特性,服务器无法主动推送内容到客户端,这使得在不完全刷新页面的情况下实现页面间的导航变得复杂。为了克服这一限制,开发者利用浏览器的哈希(#)功能创建了一种轻量级的路由解决方案——哈希路由。

哈希路由原理

哈希路由利用了URL中的哈希部分(即#后面的内容),当哈希值发生变化时,浏览器不会重新加载整个页面,而是触发hashchange事件。这样,我们可以在JavaScript中监听这个事件,根据不同的哈希值加载相应的页面组件,从而实现页面的动态更新。

哈希路由的实现机制

  • URL哈希监听:当URL中的哈希值改变时,浏览器会触发hashchange事件。这是哈希路由工作的核心,因为我们可以在这个事件上绑定一个处理函数,用来检查和响应新的哈希值。
  • 动态内容加载:在hashchange事件处理器中,我们检查URL中的哈希值,并根据该值决定加载哪个组件或页面内容。这通常涉及到使用AJAX请求或从预加载的数据中选择正确的部分来更新DOM。
  • 视图更新:一旦确定了要显示的内容,我们就可以更新DOM,只替换那些需要改变的部分,而不需要重新加载整个页面。
<!DOCTYPE html> 
<html lang="en"> 
<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> 
        </ul> 
     </nav> 
     <!-- router-view --> 
     <div id="container">
     </div> 
     
<script>
// hash 已经实现了url的改变 页面没有刷新, SPA的一种可能
        // #/page1  page1 -> container
        // #/page2  page2 -> container
        // #/page3  page3 -> container
    class HashRouter {
    constructor() {
       this.routes = {};  // 存储路由映射的哈希表
        window.addEventListener('hashchange', this.load.bind(this), false); // 添加hashchange事件监听器,调用load方法
    }
    register (hash, callback = function() {}) { // 注册路由,将特定的hash值映射到一个回调函数
        this.routes[hash] = callback;
    }
    registerIndex(callback = function() {}) { // 注册首页的回调函数
        this.routes['index'] = callback;
    }
    load () { // 路由加载函数
        let hash = location.hash.slice(1); // 获取当前URL的hash值,去除开头的#  去掉# 方为路由
        let handler; // 将要执行的处理函数
        if(!hash) { // 如果hash为空,加载首页
            handler = this.routes['index'];
        } else { // 否则,加载对应hash的页面
            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'); // 注册page1路由
router.register('/page2', function(){
    console.log(this, this.routes); // 打印当前上下文和所有路由
    container.innerHTML = 'Page2'; // 更新容器内容
});
router.register('/page3', () => container.innerHTML = 'Page3'); // 注册page3路由
console.log(router.routes); // 打印路由表
router.load(); // 初始加载,根据当前hash值执行相应的处理函数

在这段代码中,我们定义了一个HashRouter类,它负责处理页面的路由逻辑:

  1. 构造函数:创建一个空的routes对象来存储不同的哈希值和它们对应的回调函数。然后添加hashchange事件监听器,以便每当URL的哈希部分发生变化时,都能执行load方法。
  2. 注册路由registerregisterIndex方法允许我们将特定的哈希值与页面内容加载函数关联起来。这些方法填充routes对象,使其成为哈希值和处理函数之间的映射表。
  3. 加载页面内容load方法读取当前的哈希值,查找与之相关的处理函数,并执行它。如果哈希值不存在于routes对象中,则默认加载首页(通过registerIndex方法注册)。
  4. 页面内容更新:在处理函数中,我们直接修改页面容器的innerHTML属性,用新的内容替换旧的内容,从而实现页面的动态更新。创建了HashRouter的实例,并注册了四个路由:首页、page1、page2和page3。每个路由都关联了一个处理函数,这个函数负责更新<div id="container">内的内容。最后,调用router.load()来初始化路由系统,根据当前URL的哈希值加载正确的页面。

实现效果如下:

实现一个简单的哈希路由系统(Hash Router):单页应用中的URL管理与页面切换

哈希路由因其简单性和广泛的浏览器兼容性,依然在许多项目中占有一席之地,尤其是对于需要快速原型设计或在较老版本浏览器上运行的应用程序。理解哈希路由的基本原理及其在SPA中的作用,可为构建现代Web应用打下坚实的基础。

转载自:https://juejin.cn/post/7392422919249805349
评论
请登录