javascript基礎修煉(6)——前端路由的基本原理

来源:https://www.cnblogs.com/dashnowords/archive/2018/09/18/9671213.html
-Advertisement-
Play Games

【造輪子】是筆者學習和理解一些較複雜的代碼結構時的常用方法,它很慢,但是效果卻勝過你讀十幾篇相關的文章。為已知的API方法自行編寫實現,遇到自己無法復現的部分再有針對性地去查資料,最後當你再去學習官方代碼的時候,就會明白這樣做的價值,總有一天,你也將有能力寫出大師級的代碼。 一. 前端路由 現代前端 ...


【造輪子】是筆者學習和理解一些較複雜的代碼結構時的常用方法,它很慢,但是效果卻勝過你讀十幾篇相關的文章。為已知的API方法自行編寫實現,遇到自己無法復現的部分再有針對性地去查資料,最後當你再去學習官方代碼的時候,就會明白這樣做的價值,總有一天,你也將有能力寫出大師級的代碼。

一. 前端路由

現代前端開發中最流行的頁面模型,莫過於SPA單頁應用架構。單頁面應用指的是應用只有一個主頁面,通過動態替換DOM內容並同步修改url地址,來模擬多頁應用的效果,切換頁面的功能直接由前臺腳本來完成,而不是由後端渲染完畢後前端只負責顯示。前端三駕馬車Angular,Vue,React均基於此模型來運行的。SPA能夠以模擬多頁面應用的效果,歸功於其前端路由機制

前端路由,顧名思義就是一個前端不同頁面的狀態管理器,可以不向後臺發送請求而直接通過前端技術實現多個頁面的效果。angularjs中的ui-router,vue中的vue-router,以及react的react-router均是對這種功能的具體實現。

既然前端路由這麼牛逼,那必須的好好研究一下。

二. 兩種實現方式及其原理

常見的路由插件中兩種方式都是支持且可以切換的,例如angularjs1.x中就可以通過以下代碼從Hash模式切換到H5模式:
$locationProvider.html5Mode(true);
切換到HTML5的路由模式,主要用於避免url地址中包含#而引發的問題。

1.HashChange

1.1 原理

HTML頁面中通過錨點定位原理可進行無刷新跳轉,觸發後url地址中會多出# + 'XXX'的部分,同時在全局的window對象上觸發hashChange事件,這樣在頁面錨點哈希改變為某個預設值的時候,通過代碼觸發對應的頁面DOM改變,就可以實現基本的路由了,基於錨點哈希的路由比較直觀,也是一般前端路由插件中最常用的方式。

1.2 應用

下麵通過一個實例看一下,當點擊angularjs的連接時,可以看到控制台列印出了相應的信息。

2.HTML5 HistoryAPI

2.1 原理

HTML5History API為瀏覽器的全局history對象增加的擴展方法。一般用來解決ajax請求無法通過回退按鈕回到請求前狀態的問題

在HTML4中,已經支持window.history對象來控制頁面歷史記錄跳轉,常用的方法包括:

  • history.forward(); //在歷史記錄中前進一步
  • history.back(); //在歷史記錄中後退一步
  • history.go(n): //在歷史記錄中跳轉n步驟,n=0為刷新本頁,n=-1為後退一頁。

在HTML5中,window.history對象得到了擴展,新增的API包括:

  • history.pushState(data[,title][,url]);//向歷史記錄中追加一條記錄
  • history.replaceState(data[,title][,url]);//替換當前頁在歷史記錄中的信息。
  • history.state;//是一個屬性,可以得到當前頁的state信息。
  • window.onpopstate;//是一個事件,在點擊瀏覽器後退按鈕或js調用forward()、back()、go()時觸發。監聽函數中可傳入一個event對象,event.state即為通過pushState()或replaceState()方法傳入的data參數。

2.2 應用

瀏覽器訪問一個頁面時,當前地址的狀態信息會被壓入歷史棧,當調用history.pushState()方法向歷史棧中壓入一個新的state後,歷史棧頂部的指針是指向新的state的。可以將其作用簡單理解為 假裝已經修改了url地址併進行了跳轉 ,除非用戶點擊了瀏覽器的前進,回退,或是顯式調用HTML4中的操作歷史棧的方法,否則不會觸發全局的popstate事件。

在下麵的示例中,點擊導航按鈕,可以看到url地址欄發生了變化,且控制台列印出了響應的信息。

3.hash 和 history API對比

對比 hash路由 History API 路由
url字元串 正常
命名限制 通常只能在同一個document下進行改變 url地址可以自己來定義,只要是同一個功能變數名稱下都可以,自由度更大
url地址變更 會改變 可以改變,也可以不改變
狀態保存 無內置方法,需要另行保存頁面的狀態信息 將頁面信息壓入歷史棧時可以附帶自定義的信息
參數傳遞能力 受到url總長度的限制, 將頁面信息壓入歷史棧時可以附帶自定義的信息
實用性 可直接使用 通常服務端需要修改代碼以配合實現
相容性 IE8以上 IE10以上

三.親手造一個簡單的前端路由插件

造輪子,不是為了把它裝在你的車上,而是當你在荒郊野外開車而輪子出了問題時多一種選擇。

接下來就自己動手實現一個前端路由的插件吧~

3.1基於Hash的前端路由插件myHashRouter.js

我們希望實現的功能是:

  • 1.引入MyHashRouter.js
  • 2.通過when()方法來定義若幹不同的路由狀態
  • 3.通過init()方法啟動路由功能
  • 4.通過點擊導航實現前端路由切換

首先編寫js骨架,如圖所示:

;(function() {
    function Router() {
        //記錄路由的跳轉歷史
        this.historyStack = [];
        //記錄已註冊的路由信息
        this.registeredRouter = [];
        //路由匹配失敗時跳轉項
        this.otherwiseRouter = {
            path: '/',
            content: 'home page'
        }
    }

    /*
     * 啟動路由功能
     */
    Router.prototype.init = function() {

    }

     /*
     * 綁定window.onhashchange事件的回調函數
     */
    Router.prototype._bindEvents = function() {

    }

    /**
     * 路由註冊方法
     */
    Router.prototype.when = function(path, content) {

    }

    /**
     * 判斷新添加的路由是否已存在
     */
    Router.prototype._hasThisRouter = function(path) {

    }

    /**
     * 路由不存在時的指定地址
     */
    Router.prototype.otherwise = function(path, content) {

    }

    /**
     * 路由跳轉方法,主動調用時可用於跳轉路由
     */
    Router.prototype.go = function(topath) {

    }

    /**
     * 用於將對應路由信息渲染至頁面,實現路由切換
     */
    Router.prototype.render = function (content) {
     
    }

    var router = new Router();

    //將介面暴露至全局
    window.$router = router;
})();

完成了路由插件的編寫後,我們在demo中引入該庫,然後使用when()方法註冊幾個路由地址,再使用init()方法啟動路由,腳本部分代碼如下:

效果:
運行附件中的router-demo-hash.html,點擊導航按鈕,即可看到url地址欄以及內容區域同步更改。

3.2基於History API的前端路由插件myHistoryRouter.js

由於History API不支持低於IE10以下版本的瀏覽器(其他大多數現代瀏覽器基本都支持),所以我們在init()方法啟動時先進行可用性判斷,基本代碼框架與基於Hash的路由插件一致。每個方法的實現並不難寫,這裡不再贅述,筆者自己的代碼實現放在附件myHashRouter.js中,水平有限,僅供參考。

3.3集成說明

為方便理解,本例中將兩種模式分開編寫,如果是插件庫的開發,可以模仿ui-router增加一個html5mode()的方法,在init()方法啟動路由時,根據所傳的參數生成不同的路由插件的單例,也就是我們常說的工廠模式來實現即可。

四.後記

  • 造車輪是一個很好的學習方式,雖然自己造的車輪很簡陋,但是對於理解工具的底層原理卻很有幫助。
  • 本例只是編寫了一個路由工具的基本骨架,真正的路由工具還需要做很多功能擴展,個別功能的複雜度也會很高,例如路徑的正則匹配,懶載入,組合視圖,嵌套視圖,路由動畫等等,有興趣的小伙伴可以在本例提供的框架上進行學習擴展。
  • 附件說明:
    • index_h5history.html —— history API基本用法演示demo
    • index_hashchange.html —— hashchange基本用法演示demo
    • router-demo-hash.html —— 引用了myHashRouter.js的demo
    • myHashRouter.js —— 自己開發的基於hash簡易路由插件
    • router-demo-hash.html —— 引用了myHashRouter.js的demo
    • myHistoryRouter.js —— 自己開發的基於historyAPI的簡易路由插件
    • router-demo-history.html —— 引用了myHistoryRouter.js的demo

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 資源位置:百度網盤/Oracle+PL/SQL 一、Oracle安裝與配置 Oracle 11g 最好安裝在Win7上,Win10會有各種不相容問題。 先安裝Oracle資料庫,database資料庫端,去掉郵件勾選,點擊下一步,基本不需要修改什麼,修改儲存地址(最好只修改cdf等主目錄,子目錄不要 ...
  • 隨著近十年互聯網的迅猛發展,越來越多的人融入了互聯網——利用搜索引擎查詢詞條或問題;社交圈子從現實搬到了Facebook、Twitter、微信等社交平臺上;女孩子們現在少了逛街,多了在各大電商平臺上的購買;喜歡棋牌的人能夠在對戰平臺上找到世界各地的玩家對弈。在國內隨著網民數量的持續增加,造成互聯網公... ...
  • 首先將mysql解壓,公司的mysql解壓後自帶my.ini文件,結構如下: 在my.ini文件中配置的data路徑在my文件夾下,需要刪掉,然後修改my.ini文件中basedir和datadir路徑,我的mysql是在D:\mysql 打開cmd命令視窗cd到mysql下的bin文件夾,執行以下 ...
  • 已提前最小化安裝centos7.5和oracle 11g r2裸資料庫軟體,記錄下手工建庫過程,方便瞭解dbca建庫原理。 1.環境變數設置 #設置環境變數 cat >> /home/oracle/.bash_profile > /home/oracle/.bashrc > $ORACLE_HOME... ...
  • 第一步 定義要描述的數據集 當我們決定將數據存儲下來的時候,我們首先要回答的一個問題就是:“我打算存儲什麼樣的數據?這些數據之間有什麼關係?實體之間有什麼關係?實體的屬性之間有什麼關係”。 為了說明問題,我們這兒舉例的場景是要描述 庫存清單的資料庫,庫存清單數據 包括 物料名稱、數量、規格大小、狀態 ...
  • library not found for -lstdc++.6.0.9 原因是蘋果在XCode10和iOS12中移除了libstdc++這個庫,由libc++這個庫取而代之,蘋果的解釋是libstdc++已經標記為廢棄有5年了,建議大家使用經過了llvm優化過並且全面支持C++11的libc++庫 ...
  • 起因: 要做一個微信圖片分享的功能,但是對於大圖會如下問題: 當時沒有仔細查看錯誤日誌,單純的以為是圖片太大的問題。 分享圖片代碼: 解決過程: 想法一: 查看微信的文檔,發現如下信息: 初步判定是略縮圖過大導致的,準備對略縮圖進一步壓縮。 但是在調試過程中發現略縮圖並沒有超過32K,於是這種想法不 ...
  • 概述 Glide是一個圖片載入框架,使得我們可以輕鬆的載入和展示圖片 Glide4.x新增apply()來進行設置,apply可以調用多次,但是如果兩次apply存在衝突的設置,會以最後一次為準 新增RequestOptions對象,用來存放設置 添加依賴 Gilde的圖片載入 基本實例 with( ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...