@js_tut翻譯:瘋狂的技術宅javascript
https://www.freecodecamp.org/...html
未經容許嚴禁轉載前端
當你想到路由時,一般會想到相似 React 之類的庫。但實際上,這些庫和框架仍然使用 vanilla JavaScript。那麼該怎麼實現呢?java
我但願這個「JavaScript 路由教程」可以幫你瞭解如何用原生 JS 寫出本身的路由。程序員
我遇到了不少出於各類緣由想要本身建立路由的人。既然你看到本文,那意味着你可能也是其中的一個!面試
最重要的是,使用 vanilla JS router 能夠減小你對框架的依賴。正則表達式
只要你瞭解實現它所涉及的全部部分,就能夠相對容易的在原生 JavaScript 中建立本身的路由。segmentfault
如下是製做本身的 JS router 時要了解的關鍵事項:後端
首先,咱們將處理 History API。數組
我看過不少沒有提到 JavaScript History API 的 vanilla JS router 教程。太糟糕了,由於單擊瀏覽器的「後退」和「前進」按鈕與瀏覽歷史記錄中的 URL 導航有關。若是沒有 History API,就沒法談論路由。
我將簡單地對的 HTML、CSS 和 JavaScript 進行註釋。
先讓咱們仔細研究構建 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 元素中的內容徹底取決於你本身和你的後端設計。