你真的會vue-router嗎?

Mrlgm發表於2019-03-18

前記

vue-router是我們大家都知道的 Vue.js 的官方路由管理器,相信每個熟悉 Vue 的人都有用過。但對於它的原理不知道大家有沒有思考過,上週末大致看了一下vue-router的原始碼,理解了它的思路,接下來就讓我用簡單的幾行程式碼去實現它吧。這次實現我主要講解的是hash路由,history路由原理差不多,但需要後端配合。

下面是實現的最終效果圖

你真的會vue-router嗎?

可以看出頁面並沒有重新整理

原始碼在這裡:Mrlgm

router-link的本質

對於router-link編譯後的實際標籤,相信細心的同志早就發現了那其實只是一個a標籤

<router-link to="/foo">Go to Foo</router-link>
複製程式碼

會被轉化成

<a href="/foo" target="_self">Go to Foo</a>
複製程式碼

阻止a標籤的預設事件,手動來更換url

我們都知道a標籤不可避免的會造成頁面跳轉或者重新整理,這個時候我們需要手動阻止它的預設事件

 e.preventDefault()
複製程式碼

preventDefault是阻止預設事件,並不是阻止冒泡,這我們要搞清楚。阻止預設事件之後會造成一個問題,那就是URL也不會重新整理了

沒有關係,我們可以手動去更改URL,整體程式碼就是這樣子了

<a id="router1" href="/hhh" target="_self">跳轉到hhh頁面</a>

router1.addEventListener('click', function (e) {
    e.preventDefault()
    location.hash = `#${e.target.pathname}`
})
複製程式碼

監聽URL的變化,實現頁面內容的切換

頁面URL的變化,hash模式的話,只需要監聽hashchange就可以發現頁面的變化,只要監聽到了事件,我們就可以來進行頁面的操作了,程式碼如下

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

window.addEventListener('hashchange', function (e) {
    let arr = e.newURL.split('#')
    if (arr[1] === '/') {
        root.innerText = '這是主頁'
    } else if (arr[1] === '/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,有興趣的可以再看一下,實際情況中要考慮的因素肯定比我寫的要複雜的多,比如路由守衛、程式設計式跳轉,有興趣的話可以去想想如何實現的,我只是起一個拋磚引玉的作用,大家一起加油

相關文章