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模拟页面改变)

相关推荐
逐·風4 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Devil枫4 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
尚梦5 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
GIS程序媛—椰子5 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
前端青山6 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
毕业设计制作和分享6 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
鱼跃鹰飞8 小时前
大厂面试真题-简单说说线程池接到新任务之后的操作流程
java·jvm·面试
清灵xmf8 小时前
在 Vue 中实现与优化轮询技术
前端·javascript·vue·轮询
大佩梨8 小时前
VUE+Vite之环境文件配置及使用环境变量
前端
GDAL8 小时前
npm入门教程1:npm简介
前端·npm·node.js