vue-router history模式的实现原理

        各位客爷大家好,疫情已经肆虐了我们大半年的时间了,不知各位有没有在这个非常时期逆流而上找到自己心仪的工作呢~

        在下今天主要来和各位一起讨论一下vue-router history模式的实现方法

        一,经典案例

        事情的起因还要追溯于近期的一次提测,切换场景(一个真实的case,如果您只想get干货可以越过人生分割线来忽略):

        ———————————————  人生分割线    —————————————————

        我司的后台系统使用vue+vue-router这种技术栈来实现,由于业务需求较多,这些页面也就多到左侧菜单栏无法承载的地步,所以我们每个人可见的左侧显示菜单,都是通过一个权限系统配制而成的。

大概是长这个样子吧

        左侧的菜单栏点击链接之后跳转方式是window.location.href,这次我们重构将之前的hash模式改为了history模式,但是问题来了:

        由于之前系统一直是以hash模式url跳转,所以后台配置的路径一直是hash试的全路径,例如:

                http://XXX.com/#home

                http://XXX.com/#list

        但是当我们改为了history模式之后(http://XXX.com/list),问题出现了,每一次页面跳转都造成了页面刷新。

        我在这个跳转逻辑里发现其实之前其实是有history模式的兼容的,只要从后台配置的路径不是全url路径,是一个path的话,那就会使用vue-router的push方法跳转,于是这个问题算是解决了。但是当我们组妹子娇娇问我为什么之前使用全路径都OK的时候,我只是回复了她一句因为之前是hash模式,如果换位思考的话,我对这个回答并不满意,因此我想通过这篇博文整体解释一下为什么之前使用hash模式可以,但是history会出现问题。

        ————————————————  人生分割线    ————————————————

        二,原理分析

        终于要上干货了,我们来针对这几个问题一一分析:

        1,为什么之前hash模式,菜单配置全路径页面跳转不刷新?

            根据http协议所示,url中hash改变请求是不会发送到服务端的,不管你怎么location跳转,或者url上直接加上hash值回车,他都一样固执,就是不和服务器老大说。

            但是我们的系统里又引入了vue-router,其中hashchange这个事件监听又监听到了hash的变化,从而触发了组件的更新,也就绘制出了相应的页面。

        2,为什么换成history模式,每次点击菜单的导航都会页面刷新?

            首先我们来看一下一个正确的history模式下,首页刷新到显示的整体流程:

                1,将这个完整的url发到服务器ng

                2,ng需要配置用这个uri再指给给前端index.html(这里我插一句哈,为什么要这么做呢,因为根本没有任何一个服务器提供了这个url路由,如果直接访问的话就是404,所以需要指回给前端,让前端自己去根据path来显示)

                3,此时ng将这个请求指向了前端index.html,index.html中开始加载js,js中已有vue-router的代码,vue-router自动触发了popstate这个事件,在这个事件回调中,绘制了这个path下对应的页面组件

            接着我们再来看一下vue-router push方法的页面跳转流程:

                1,vue-router调用push方法首先会使用pushstate变换页面url(仅仅变化url,页面不变)

                2,紧接着根据push方法中传入的params找到对应的组件【页面】

                3,载入对应页面组件,跳转完毕

            【划重点】vue-router的push跳转或者replace跳转是不需要请求服务器的!

            但是我们如果使用window.location.href来做这个页面跳转,就基本上和web1.0没什么区别,一定会先请求到服务器,再由服务器下发资源,导致页面刷新~

            讲到这里我想妹子和我的困惑也都迎刃而解了,最近也有面试过一些前端,简历上也都有写搞过vue-router的history模式,配置ng之类的,但是当我问为什么配上ng就可以正常访问了,或者说ng是怎么实现页面正常访问的,基本上都能刷下一大波,在下认为搞技术的话一定要有敬畏之心,做项目要严谨,不能浅尝辄止#@$!^$#&%.....

            如果各位还想听在下聊聊vue-router中使用的pushState方法的话,请越过下面的涨芝士分割线,如果已经对这部分了如指掌的话,那么就祝您找到自己称心的工作了

        ————————————————  涨芝士分割线    ————————————————

        三,知识点讨论

            在下刚开始用 vue-router 的时候就好奇,为什么$router跳转页面的时候api是push,这分明是一个数组的方法嘛~但是后来在下阅读了vue-router的源码,发现犹大是用了pushState来做纯前端的页面跳转,在下不禁拍了下大腿,我*高招啊。

            这个pushState单纯的做了一个url的变化,并且在路由队列里加上了这条新的url的记录,所以如果您在page1页面使用了pushState这个方法,页面不会变化,只是浏览器地址栏会发生更新,且浏览器的回退按钮变成了可点击状态!

            所以,犹大在使用pushState将url改变之前,先做了页面组件的刷新,也就模拟出了页面跳转的样子。

            那么,如果我刷新首页,又或者前进后退,怎么再更新页面组件呢?答案就是使用popstate来做事件监听,当用户首次访问,前进或后退的时候,都会触发popstate事件,再由popstate来做当前页,上一页等页面的记录和绘制。

—————————————————  涨芝士分割线  —————————————————

        今天就聊到这了,最近疫情北京又变中高风险地区了,本来和老婆打算去玩个迪士尼来庆祝下一周年,看来也泡汤了。最近公司组织架构调整,我们部门在风波中也被撕扯分裂到了各个新项目组,之前一起并肩奋斗的小伙伴也走了一小半,但是至少,我们还有张照片~

你可能感兴趣的:(vue-router history模式的实现原理)