HashRouter的实现原理,带你一起手写。

在多页应用的开发中,每个页面都是独立的HTML文件。当用户在应用中导航到新页面时,浏览器会发送全新的HTTP请求到服务器,获取该页面的所有资源(HTML、CSS、Javascript),也就是说,每次页面跳转都会经历一个完整的加载过程,当网速较慢或浏览器性能较低时,就会出现白屏页面,让用户不明所以,直接离开网站。

那么有什么方法既能不刷新整个页面,又能完成页面跳转呢?一起来看看vue3中hashRouter的实现原理.....

一、vue3中的hashRouter

  • import { createRouter, createWebHashHistory } from 'vue-router'引入模块。
  • 实例化并配置路由,
css 复制代码
const router = createRouter({
    history: createWebHashHistory(),
    routes : [
        {
            path: '/home',
            component: ()=>import('../views/Home.vue')
        },
        {
            path: '/bot',
            component: () => import('../views/Bot.vue')
        },
        {
            path: '/hot',
            name:'hot',
            component: () => import('../views/Hot.vue'),
        }
    ]
})
  • 使用createWebHashHistory()创建的路由器会在URL中使用#字符作为前缀来区分不同的路由。
  • URLhash部分为/home时,加载Home.vue组件......
  • hash部分指的是URL#符号后面跟随的字符串。

当我们进行类似导航栏的功能时,只有部分内容被动态更新,而无需重新加载整个页面,提供了非常流畅的用户体验,类似原生应用的感觉,同时可以减少浏览器负载,不需要频繁的请求完整的页面资源。

二、锚链接实现改变URL的hash部分

我们看见了vue3中页面更新时只有URL的hash部分发生了改变,那么有什么方法能改变这部分呢?

使用锚链接

在HTML中,使用<a>标签结合hash来创建锚链接。用户点击锚链接时,window.location.hash将被更新,从而触发hashchange事件,这是接下来hashRouter实现的核心。

三、、手写hashRouter

基本原理

使用纯Javascript来监听hashchange事件,根据hash的变化来更新DOM。

xml 复制代码
<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>
    <div id="container"></div>
    <script>
        class HashRouter{
            constructor(){
                this.routes = {}  //page => Component
                window.addEventListener('hashchange',
                this.load.bind(this),false)
            }

            register(hash,callback = function(){}){
                this.routes[hash] = callback 
            }
            load(){
                let hash = location.hash.slice(1)  //去掉# 就是路由 
                console.log(hash,'///');
                let handler
                if(!hash){
                    //首页
                    handler = this.routes['/index']
                }else{
                    //相应页面
                    handler = this.routes[hash]
                }
                handler && handler.call(this)
            }
            //注册首页
            registerIndex(callback = function(){}){
                this.routes['/index']  = callback
            }
        }
        let router = new HashRouter()
        let container = document.getElementById('container')
        router.registerIndex(()=>{
            container.innerHTML = '我是首页'
        })
        router.register('/page1',()=>{
            container.innerHTML = '我是page1'
        })
        router.register('/page2',function(){
            console.log(this,this.routes);
            container.innerHTML = '我是page2'
        })
        router.register('/page3',()=>{
            container.innerHTML = '我是page3'
        })
        console.log(router.routes);//查看添加的方法,用于handler执行
        router.load()
    </script>
</body>
  • hashchage事件监听器,监听hash部分的内容变化。
  • 注册路由函数register,接收两个参数,一个为要注册路由的hash部分,一个为回调函数。
  • 加载路由函数load,获取URL中的hash部分,输出控制台,清晰明了的看一下是什么东西,handle函数,执行对应hash部分的routes中的函数,用于相应页面的显示。
  • 如果hash部分为空,则执行routes中'/index'所对应的函数,如果不为空,执行相应hash部分的函数,并显示相应页面。
  • handler && handler.call(this)判断routes中是否存在handler是很有必要的,因为用户在输入URL中可能输错,这是handlerundefined,程序崩溃,这样使代码更加健壮。.call确保了函数内部的this正确指向HashRouter实例对象,方便拿到实例对象的所有信息,便于后续操作。
  • 单独创建注册首页函数,功能和注册路由函数register差不多。

实例化HashRouter对象,执行构造函数constructor中的逻辑。 注册几个页面的路由,实际上是往构造函数中的this.routes = {}中添加方法,用于handler的执行。router.load()完成进页面时的首次加载。

我们在看一下routes中的内容和handle函数的this指向。

handler执行routes中'/page2'对应的函数时,this指向的是实例对象HashRouterroutes的内容是对应hash部分内容和执行函数(改变container.innerHTML模拟页面改变)

相关推荐
活宝小娜1 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点1 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow1 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o1 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
开心工作室_kaic2 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā2 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
沉默璇年3 小时前
react中useMemo的使用场景
前端·react.js·前端框架
yqcoder3 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
2401_882727573 小时前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
SoaringHeart4 小时前
Flutter进阶:基于 MLKit 的 OCR 文字识别
前端·flutter