手撕Vue-Router-知識儲備

BNTang發表於2023-11-18

前言

本文是手寫Vue-Router的第一篇,主要是對Vue-Router的知識儲備,為後面的手寫做準備。

那麼 VueRouter 怎麼實現呢?要想實現 VueRouter,首先要知道 VueRouter 它的本質是什麼。

VueRouter 的本質

VueRoute 的本質是什麼?VueRouter 的本質就是根據 "不同的 hash 值" 或者 "不同的路徑地址", 將不同的內容渲染到 router-view 中。

再過去,我學習 VueRouter 的時候,知道 VueRouter 有兩種模式,一種是 hash 模式,一種是 history 模式。那麼這兩種模式有什麼區別呢?

hash 模式和 history 模式的區別

如果是 history 模式,那麼我們的路徑就是這樣的:http://localhost:8080/home,如果是 hash 模式,那麼我們的路徑就是這樣的:http://localhost:8080/#/home

瞭解了這些知識之後,所以實現 VueRouter 的核心關鍵點就在於如何監聽 'hash''路徑' 的變化, 再將不同的內容寫到 router-view 中。

那麼在實現 VueRouter 之前呢,我在給大家補充一下,如何監聽 'hash''路徑' 的變化。

如何監聽 hash 或 路徑 的變化

hash

首先我新建了一個 test.html 檔案,然後在裡面寫了一個 div,然後給這個 div 設定了一個 idid 的值為 html

並且在頁面當中新增了兩個 a 標籤,兩個 a 標籤的 href 分別跳轉地址為,一個是 #/home,一個是 #/about

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a href="#/home">首頁</a>
<a href="#/about">關於</a>
<div id="html"></div>
</body>
</html>

基本的結構我們搭建完畢,好了接下來我們怎麼監聽 hash 的變化呢?也非常的簡單,其實在我們原生的 JS 當中,有一個 hashchange 事件,這個事件就是用來監聽 hash 變化的(專門用於監聽 hash 變化的)。

那麼知道了監聽 hash 變化的事件之後,我們怎麼使用呢?我們可以給 window 繫結一個 hashchange 事件,然後在這個事件當中,有一個回撥函式,主要 hash 變化之後,我們就可以在這個回撥函式當中,獲取到當前的 hash 值。

那麼怎麼驗證它會執行這個回撥函式呢,我們可以在這個回撥函式當中,列印一下當前的 hash 值。

<script>
    window.addEventListener('hashchange', () => {
        console.log('當前的hash值發生了變化');
    });
</script>

好了,我們開啟瀏覽器,然後點選首頁,我們可以看到控制檯列印了一句話,說明我們的 hash 值發生了變化,看到這一點就可以驗證我的一個說法。

接下來我們要做的就是將內容渲染到 div 中,我們先簡單的來將 hash 值寫入到 div 中。

window.addEventListener('hashchange', () => {
    const currentHash = location.hash.slice(1);

    document.querySelector('#html').innerHTML = currentHash;
});

我們開啟瀏覽器,點選首頁,我們可以看到 div 中的內容變成了 home,點選關於,我們可以看到 div 中的內容變成了 about

將來我們是不是根據這個獲取到對應的元件,然後將元件渲染到 div(某一個容器當中)中就可以了。

好了到這裡我們的監聽 hash 就可以,可以了之後還沒完,可以了之後有沒有這麼一種情況,就是我們第一次開啟頁面的時候我們地址上面是沒有 hash 值的,還有可能就是我們位址列是有 hash 值的這種情況,是不是有可能,對吧,我們先來看看我們第一次開啟頁面的時候,有 hash 值我們的容器顯示的是什麼。

我們可以看到我們的容器顯示的是空的,那麼我們怎麼解決這個問題呢?我們可以在頁面載入的時候,手動的觸發一次 hashchange 事件,這樣我們就可以在頁面載入的時候,將內容渲染到 div 中。

首先我們在 window 上面繫結一個 load 事件,然後在這個事件當中,我們手動的觸發一次 hashchange 事件。

window.addEventListener('load', () => {
    const currentHash = location.hash.slice(1);
    document.querySelector('#html').innerHTML = currentHash;
});

我們開啟瀏覽器,我們可以看到我們的容器當中顯示的是 home,這樣我們就解決了第一次開啟頁面的時候,我們的容器顯示的是空的這個問題。

路徑

到此為止,我們就可以監聽 hash 的變化了,那麼我們怎麼監聽路徑的變化呢?我們可以使用 historypushState 方法,這個方法可以改變路徑,然後我們就可以監聽路徑的變化了。

在看路徑地址之前,我們先將基本的內碼表面結構搭建一下,路徑與之前的 hash 是不一樣的,所以我們這裡的 a 標籤就不能使用 href 屬性了,路徑我們可以給 a 標籤繫結一個事件,繫結一個方法然後在這個方法當中來改變路徑。

頁面樣式的基本結構程式碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a onclick="go('/home')">首頁</a>
<a onclick="go('/about')">關於</a>
<div id="html"></div>
<script>
    function go(path) {
    }
</script>
</body>
</html>

定義了一個 go 方法,接收一個引數 path,接下來要做的事情就是根據這個 path 來改變路徑,這個我們要怎麼實現呢?這裡我們可以藉助一個 history 物件,在 history 物件當中有一個 pushState 方法,這個方法接收三個引數,第一個引數是 state,第二個引數是 title,第三個引數是 url

pushState 方法引數:

  • state:一個與指定網址相關的狀態物件,popstate 事件觸發時,該物件會傳入回撥函式。如果不需要這個物件,此處可以填 null。
  • title:新頁面的標題,但是所有瀏覽器目前都忽略這個值,因此這裡可以填 null。
  • url:新的網址,必須與當前頁面處在同一個域。瀏覽器的位址列將顯示這個網址。

那麼我們怎麼使用呢?我們可以在 go 方法當中,呼叫 pushState 方法,然後將 path 傳入到 pushState 方法當中,這樣我們就可以改變路徑了。

history.pushState(null, null, path);

好了,我們開啟瀏覽器,點選首頁,我們可以看到我們的路徑變成了 http://localhost:8080/home,點選關於,我們可以看到我們的路徑變成了 http://localhost:8080/about

沒問題之後,我們再將內容渲染到 div 中,我們可以在 go 方法當中,獲取到當前的路徑,然後將路徑寫入到 div 中。

document.querySelector('#html').innerHTML = path;

我們開啟瀏覽器,點選首頁,我們可以看到我們的容器當中顯示的是 home,點選關於,我們可以看到我們的容器當中顯示的是 about

到此為止,我們就可以監聽路徑的變化了,好了知道這些內容之後,還有一個注意點需要給大家說一下:

注意點

我們先基於 IDEA 執行我們的專案,然後,點選一下首頁這個時候我們的路徑與容器內容都是 /home, 好,我們這個時候將地址複製一下,例如現在路徑已經變為了 http://localhost:63342/home ,我們在點選一下關於,我們可以看到我們的路徑變為了 http://localhost:63342/about, 好,這個時候我們的關鍵點就要來了:

正如上圖所示,我們的路徑變為了 http://localhost:63342/home, 但是容器的內容還是 about,這是為什麼呢?所以說這個東西我們也需要進行同步一下,那麼我們手動新增了路徑那麼它怎麼知道我們有沒有前進與後退呢?非常簡單,其實在我們的原生 JS 當中,又有一個事件,這個事件就是 popstate 事件,透過這個事件,我們就可以監聽到前進與後退的點選,透過這個事件監聽了前進與後退的點選之後,它會執行一個回撥函式,我們在這個回撥函式當中,就可以處理之前的問題了。

更改我們的程式碼,我們可以在 window 上面繫結一個 popstate 事件,然後在這個事件當中,我們可以獲取到當前的路徑,然後將路徑寫入到 div 中。

window.addEventListener('popstate', () => {
    document.querySelector('#html').innerHTML = location.pathname;
});

測試注意點

我們開啟瀏覽器,點選首頁,我們可以看到我們的容器當中顯示的是 home,點選關於,我們可以看到我們的容器當中顯示的是 about,好,這個時候我們的關鍵點就要來了,我們點選一下瀏覽器的前進與後退,我們可以看到我們的容器當中顯示的是 homeabout,這樣我們就解決了這個問題。

總結

到此為止,我們瞭解瞭如何監聽 hash 與路徑的變化,並且瞭解到瞭如何監聽前進與後退的點選,hash 與路徑的變化。

本篇文章就到這裡,感謝大家的閱讀,如果有什麼不足的地方,歡迎大家指出,我會及時的進行修改。

相關文章