你真的会vue-router吗?

1,467 阅读2分钟

前记

vue-router是我们大家都知道的 Vue.js 的官方路由管理器,相信每个熟悉 Vue 的人都有用过。但对于它的原理不知道大家有没有思考过,上周末大致看了一下vue-router的源码,理解了它的思路,接下来就让我用简单的几行代码去实现它吧。这次实现我主要讲解的是hash路由,history路由原理差不多,但需要后端配合。

下面是实现的最终效果图

可以看出页面并没有刷新

源码在这里:Mrlgm

router-link的本质

对于router-link编译后的实际标签,相信细心的同志早就发现了那其实只是一个a标签

<router-link to="/foo">Go to Foo</router-link>

会被转化成

<a href="#/foo">Go to Foo</a>

阻止a标签的默认事件,手动来更换url

我们都知道a标签不可避免的会造成页面跳转或者刷新,这个时候我们需要手动阻止它的默认事件

 e.preventDefault()

preventDefault是阻止默认事件,并不是阻止冒泡,这我们要搞清楚。阻止默认事件之后会造成一个问题,那就是URL也不会刷新了

没有关系,我们可以手动去更改URL,整体代码就是这样子了

<a id="router1" href="/hhh">跳转到hhh页面</a>

router1.addEventListener('click', function (e) {
    e.preventDefault()
    location.hash = `${e.target.hash}`
})

监听URL的变化,实现页面内容的切换

页面URL的变化,hash模式的话,只需要监听hashchange就可以发现页面的变化,只要监听到了事件,我们就可以来进行页面的操作了,代码如下

<div id="root"></div>

window.addEventListener('hashchange', function (e) {
    let hash = e.target.location.hash
    if (hash === '#/') {
      root.innerText = '这是主页'
    } else if (hash === '#/hhh') {
      root.innerText = '这是hhh页'    
    }
})

注意,history模式监听的事件和hash模式不一样,有兴趣的可以自己去看一下,但是思想其实是一致的

页面刷新内容不变

因为,hashchange只有在URL改变的时候才会触发,所以当我们刷新页面的时候,也要去匹配URL,非常简单,代码如下

if (window.location.hash === '#/') {
    root.innerText = '这是主页'
} else if (window.location.hash === '#/hhh') {
    root.innerText = '这是hhh页'
}

总结

到此为止,简单的vue-router就实现了,参考vue-router的源码主要有这么两篇link.jshash.js,有兴趣的可以再看一下,实际情况中要考虑的因素肯定比我写的要复杂的多,比如路由守卫、编程式跳转,有兴趣的话可以去想想如何实现的,我只是起一个抛砖引玉的作用,大家一起加油