如何制作自己的原生JavaScript路由

前言

當你想到路由時,通常會想到類似react之類的庫。但實際上,這些庫和框架仍然使用vanillaJavaScript。那麼該怎麼實現呢?

我希望這個“JavaScript路由教程”能夠幫你瞭解如何用原生js寫出自己的路由。

簡介

我遇到瞭很多出於各種原因想要自己創建路由的人。既然你看到本文,那意味著你可能也是其中的一個!

最重要的是,使用vanillajsrouter可以減少你對框架的依賴。

隻要你瞭解實現它所涉及的所有部分,就可以相對容易的在原生 JavaScript 中創建自己的路由。

以下是制作自己的JS router時要瞭解的關鍵事項:

1.原生 JS 路由的關鍵是location.pathname屬性。

2.偵聽 “popstate”事件以響應.pathname的更改。每當在瀏覽器的地址欄中輸入新的 URL,但我們不想刷新頁面時,就會發生這種情況,我們隻是想通過加載新內容來刷新視圖。

3.你可以選擇將路由存儲在routes[]數組中。

4.必須用JavaScript 正則表達式(RegEx)才能解析 URL。

5.如果希望將路由集成到本機瀏覽器體系結構中,那麼對history和history.pushState(JavaScript 的 History API)的基本瞭解至關重要。

首先,我們將處理 History API。

JavaScript 的 History API

我看過很多沒有提到 JavaScript History API 的vanilla JS router教程。太糟糕瞭,因為單擊瀏覽器的“後退”和“前進”按鈕與瀏覽歷史記錄中的 URL 導航有關。如果沒有 History API,就無法談論路由。

1.history.back()與history.go(-1)相同,或者當用戶在瀏覽器中單擊Back按鈕時。你可以用任何一種方法達到相同的效果。

2.當用戶按下瀏覽器的Forward按鈕時,將執行history.forward(),它等效於history.go(1)”。

3.go()與.back()和forward()方法相似,不同之處在於你可以指定瀏覽器歷史記錄棧中要前進或後退的步數。 。

4.pushState()會將新狀態推送到 History API。

5..length屬性是會話歷史記錄中的元素數。

6..state屬性用於查找狀態,而無需偵聽“ popstate”事件。

實現自己的原生JS路由

基於 History API 的 Vanilla JS 路由設置

先讓我們仔細研究構建 URL 切換器所需的最少代碼(而無需刷新頁面),然後我會向你展示其的工作方式的 GIF 動圖。

<html>
    <head>
        <title>Hello</title>
        <script type = "module">
            function select_tab(id) {
                // remove selected class from all buttons
                document.querySelectorAll(".route").forEach(item => item.classList.remove('selected'));
                // select clicked element (visually)
                document.querySelectorAll("#" + id).forEach(item => item.classList.add('selected'));
            }
            function load_content(id) {
                // Update text "Content loading for {id}..."
                // Of course, here you would do you content loading magic
                // Perhaps run Fetch API to update resources
                document.querySelector("#content").innerHTML = 'Content loading for /' + id + '...';
            }
            function push(event) {
                // Get id attribute of the box or button or link clicked
                let id = event.target.id;
                // Visually select the clicked button/tab/box
                select_tab(id);
                // Update Title in Window's Tab
                document.title = id;
                // Load content for this tab/page
                loadContent(id);
                // Finally push state change to the address bar
                window.history.pushState({id}, `${id}`, `/page/${id}`);
            }
            window.onload = event => {
                // Add history push() event when boxes are clicked
                window["home"].addEventListener("click", event => push(event))
                window["about"].addEventListener("click", event => push(event))
                window["gallery"].addEventListener("click", event => push(event))
                window["contact"].addEventListener("click", event => push(event))
                window["help"].addEventListener("click", event => push(event))
            }
            // Listen for PopStateEvent (Back or Forward buttons are clicked)
            window.addEventListener("popstate", event => {
                // Grab the history state id
                let stateId = event.state.id;
                // Show clicked id in console (just for fun)
                console.log("stateId = ", stateId);
                // Visually select the clicked button/tab/box
                select_tab(stateId);
                // Load content for this tab/page
                loadContent(id);
            });
        </script>
        <style>
            * { /* global font */
                font-family: Verdana;
                font-size: 18px;
            }
            #root { display: flex; flex-direction: row; }
            #content { display: flex;
                display: block;
                width: 800px;
                height: 250px;
                /* vertically centered text */
                line-height: 250px;
                border: 2px solid #555;
                margin: 32px;
                text-align: center;
            }
            .route {
                cursor: pointer;
                justify-content: center;
                width: 150px;
                height: 50px;
                /* vertically centered text */
                line-height: 50px;
                position: relative;
                border: 2px solid #555;
                background: white;
                text-align: center;
                margin: 16px;
            }
            .route.selected { background: yellow; }
        </style>
    </head>

    <body>

        <section id = "root">
            <section class = "route" id = "home">/home</section>
            <section class = "route" id = "about">/about</section>
            <section class = "route" id = "gallery">/gallery</section>
            <section class = "route" id = "contact">/contact</section>
            <section class = "route" id = "help">/help</section>
        </section>

        <main id = "content">Content loading...</main>
    
    </body>

</html>

核心是對的window.history.pushState({id}, ${id}, /page/${id});調用;

第一個參數是狀態的唯一 ID,第二個是“標簽標題”文本,第三個參數是你希望地址欄中要現實的路徑。這就是使瀏覽器無需重新加載頁面即可更改 URL 的原因。

結果。現在,每次我們單擊按鈕時,URL實際上都會在瀏覽器的地址欄中更改。內容框也會更新。

我們的原生 JS 路由開始運行瞭。請註意,每次單擊按鈕時,history.pushState 被觸發。我們隻需將存儲在元素的 id 屬性中的 clicked 元素的 id 傳遞給它即可:home,about,gallery等。它們應與你要導航到的實際頁面一致。當然這不是存儲頁面名稱的唯一方法,例如可以用 array [] 或其他任何方式。這就是本例中的操作方式。

當然我們還需要從服務器加載有關該位置的佈局和資源的內容。這取決於你的程序。可以是任何東西。

使“後退”和“前進”按鈕起作用

通過使用history.pushState,你將自動使Back和Forward按鈕導航到上一個或下一個狀態。這樣做會產生popstate事件。這是你必須再次更新視圖的部分。 (第一次是我們單擊按鈕時。)

但是由於該事件帶有單擊的id,因此單擊Back或Forward時很容易刷新視圖並重新加載內容。

我們在這裡沒有使用react或vue,因此在我的源代碼中load_content將負責直接在 DOM 中更新視圖。此區域可能填充瞭你的 API 加載的某些內容。由於這隻是“前端”示例,因此我無法向你展示太多內容。但這就是它在客戶端上的工作方式。

初始化服務器端的路由負載

將它們放在一起還需要再執行一個步驟。在我的例子中,隻用瞭router.html。當你第一次在 PWA 中加載此路由時,必須確保如果直接在地址欄中輸入/page/home時,它可以工作。

到目前為止,我們僅從前端更改瞭路由器地址。假定每次你導航到出現在路由按鈕上的 URL 時,實際上都會從服務器單獨加載該 URL。

因此你有責任確保/page/about將路由器和頁面的加載到應用程序的根視圖中。它還應突出顯示“current”按鈕。

實施完畢後,你的路由就完成瞭。你如何選擇重新加載#content元素中的內容完全取決於你自己和你的後端設計。

以上就是如何制作自己的原生JavaScript路由的詳細內容,更多關於制作原生JavaScript路由的資料請關註WalkonNet其它相關文章!

推薦閱讀: