哈希路由奇遇记:网页瞬移的秘籍与实践

298 阅读3分钟

在互联网的浩瀚宇宙中,HTTP协议这位老练的邮差遵循着严格的“无状态”原则,意味着它忘性极大,每次交易后都会“失忆”。服务器端无法主动敲响浏览器的门铃推送新消息,因此,当你从主页踏步迈向“第二页”的奇妙之旅时,就得重新打包行李(请求),再次出发(发送请求)。这种仪式感虽然庄重,却也拖慢了我们的步伐。

单页应用诞生

这时,一位名为“单页应用(SPA)”的超级英雄降临,它挥舞着“快速加载”的魔法棒,誓要终结白屏的尴尬。SPA的出现如同夏日里的一股清流,让网页加载快如闪电,用户体验直线飙升。想象一下,从首页瞬移到“第二页”,就像哈利波特的瞬间移动咒语,嗖的一下,画面就变了,但页面却依然稳如泰山,不带一丝卡顿。

哈希路由:一场浏览器内的“角色扮演”

而这一切的幕后推手,正是我们今天的主角——哈希路由。它利用URL中的“#”符号,巧妙地在浏览器内部开启了一场“密室逃脱”游戏。每当井号后面跟着的神秘代码变化时,浏览器就会心一笑,仿佛接收到暗号,知道是时候换上新装了,但却无需大费周章地重启整个页面。这招“瞒天过海”,让页面更新如同变魔术一般悄无声息。

这就和我们用来浏览器定位的锚链接相同,点击锚链接也同样会发生地址的改变,但是页面不会进行刷新。

路由实现

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>

其中,三个li代表着三个不同的哈希路径(#/page1#/page2#/page3),下面的container用来存放每个哈希路径下的内容,用于模拟页面更新方便看到效果。

路由管理类

class HashRouter {
        constructor() {
            this.routes = {};  // page => Component
            window.addEventListener('hashchange', 
                this.load.bind(this), false)
        }
        register (hash, callback = function() {}) {
            this.routes[hash] = callback
        }
        registerIndex(callback = function() {}) {
            this.routes['index'] = callback    
        }

        load () {
            let hash = location.hash.slice(1) // 去掉# 方是路由
            let handler;
            if(!hash) {
                //  首页 
                handler = this.routes['index']
            } else {
                // 相应页面
                handler = this.routes[hash]
            }
            handler && handler.call(this)
        }
    }
  • 构造函数constructor(): 初始化路由,并实现对hash改变(hashchange)的事件监听,如果发生改变就执行load方法。其中的,this.load.bind()不仅可以实现this的准确指向,也可以返回一个函数体,非常的好用爱用。

  • register()方法: 设置不同哈希路由的函数处理方法。

  • registerIndex()方法: 为确保没有设定路由的情况下,默认展示首页。

  • load()方法: 在路由发生改变时,查找相对应的处理函数,来实现页面更新。

实例化路由

let router = new 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()
  • 实例化路由: 创建HashRouter()的实例。
  • 获取节点: 拿到container节点,为实现后续相对应的路由处理函数执行展现的效果。
  • 创建路由: 对路由进行处理,展示不同的处理效果,即相当于页面更新。
  • 初始页面处理: 手动执行load()方法,实现首次页面加载,显示首次展现路由的对应页面。

结语

哈希路由的引入,使得网页应用能够模拟出类似原生手机应用的流畅体验。用户在SPA中浏览时,感受不到传统网页跳转的中断,仿佛置身于一个连贯、响应迅速的应用环境中。这种无缝的交互模式,极大地缩小了网页应用与原生应用之间的差距,为用户提供了一个既便捷又高效的浏览环境。

总之,哈希路由以其独特的机制,在不改变HTTP协议本质的前提下,为单页应用提供了一种高效、灵活的页面导航解决方案。它不仅提升了用户体验,还促进了Web应用向更高级形态的发展,是现代Web开发中不可或缺的利器。