vue-router路由原理


Vue-router路由原理

目前實現路由的方式有兩中,vue通過參數mode來設置,默認是hash模式。

  1. 利用URL中的hash(‘#’)來實現
  2. 利用History interface在HTML5中新增的方法

history對應的是HTML5History對象,hash對應的是HashHistory對象,abstract對應的是AbstractHistory對象。在初始化對應的history之前,會對mode做一些校驗:若瀏覽器不支持HTML5History方式(通過supportsPushState遍歷判斷),則mode設為hash,若不是在瀏覽器環境下運行,則mode設為abstract

VueRouter類中的onReady(),push()等方法只是一個代理,實際是調用的具體history對象的對應方法,在init()方法中初始化時,也是根據history對象具體的類別執行不同操作

HashHistory

Hash(‘#’)符號的本來作用是加在URL指示網頁中的位置,#本身以及它后面的字符稱之為hash,通過window.location.hash屬性來獲取

Hash雖然出現在url中,但不會被包括在http請求中,它是用來指導瀏覽器動作的,對服務端完全無用,因此改變hash不會重新加載頁面,如果是手動在url添加hash,這時可以為hash的改變添加監聽事件

Window.addEventListener(‘hashchange’,funcRef,false)

每一次改變hash(window.location.hash)都會在瀏覽器訪問歷史中增加一個記錄

執行vue里的push()方法最主要的是對window的hash進行直接賦值

Window.location.hash = route.fullPath

$router.push()  -> HashHistory.push()  -> History.transitionTo()  -> History.updateRoute() -> vm.render()

HashHistory.replace()

Replace()方法與push()方法不同之處在於,它並不是將新路由添加到瀏覽器訪問歷史棧頂,而是替換掉當前的路由,背后它實際上是調用window.location.replace方法將路由進行替換

監聽地址欄

VueRouter.push()和VueRouter.replace()是可以在vue組件的邏輯代碼中直接調用的,除此之外在瀏覽器中,用戶還可以手動在瀏覽器地址欄中輸入url,因此還需要監聽瀏覽器地址欄中路由的變化,並具有與通過代碼調用的相同響應行為,在History中通過setupListeners監聽hashchange實現:

Window.addEventListener(‘hashchange’,function () {}),當在瀏覽器地址欄直接輸入路由相當於代碼調用了replace()方法

HTML5History

History interface是瀏覽器歷史記錄棧提供的接口,back(),forward(),go()等方法,HTML5提供了pushState(),replateState()這兩個方法

Window.history.pushState(stateObject,title,url)

Window.history.replateState(stateObject,title,url)

stateObject:當瀏覽器跳轉到新的狀態時,將觸發popState事件,該事件將攜帶這個stateObject參數的副本

title:所添加記錄的標題

url:所添加記錄的url

這兩個方法有個共同特點:當調用他們修改瀏覽器歷史棧后,雖然當前url改變了,但瀏覽器不會立即發送請求該url,這就為單頁應用前端路由,更新視圖但不重新請求頁面提供了基礎

History與hash模式基本類似,只不過將對window.location.hash()直接進行賦值window.location.replate()改為調用了window.location.history.pushState()和window.location.replateState()方法,而HTML5History中添加對修改瀏覽器地址欄url的監聽popstate是直接在構造函數中執行的

Window.addEventListeners(‘popstate’,e => {// 執行相應的功能})

HTML5History需要瀏覽器的支持,vue是通過supportPushState()來檢查

除這兩中模式外,vue-router還未非瀏覽器環境准備了一個abstract模式,原理是用一個數組stack模擬除瀏覽器歷史記錄棧的功能

兩中模式比較

調用history.pushState()相比直接修改hash主要有以下優勢:

  1. pushState設置的新url可以是與當前url同源的任意url,而hash只可修改#后面的部分,故可設置與當前同文檔的url
  2. pushState設置的新url可以與當前url一模一樣,這樣也會把記錄添加到棧中,而hash設置的新的值必須與原來不一樣才會觸發記錄添加到棧中
  3. pushState通過stateObject可以添加任意類型的數據記錄中,而hash只可添加短字符串
  4. pushState可額外設置title屬性供后續使用

history模式問題

對於單頁面應用來說,理想的使用場景是僅僅在進入用用時加載index’.html,后續在網絡操作通過ajax完成,不會根據url重新請求頁面,但是如果用戶直接在地址欄中輸入並回車,瀏覽器重啟重新加載等特殊情況

Hash模式僅僅改變hash部分的內容,而hash部分是不會包含在http請求中的,就是#以及后面的是不會包含在請求當中的

http://baidu.com/#user/id      //如請求,只會發送http://baidu.com

所以hash模式下遇到根據url請求頁面不會有問題

而history模式則將url修改的就和政策請求后端的url一樣,history不帶#。http://baidu.com/user/id

如果這種向后端發送請求的話,后端沒有配置對應/user/id的路由處理,會返回404錯誤

官方推薦的解決方法是在服務端增加一個覆蓋所有情況的候選資源:如果url匹配不到任何靜態資源,則應該返回同一個index.html頁面,這個頁面就是你app依賴的頁面。同時這么做以后,服務器就不再返回404錯誤頁面,因為對於所有路徑都會返回index.html文件。為了避免這種情況,在vue應用里面覆蓋所有的路由情況,然后再給出一個404頁面。或者如果是用node.js做后台,可以使用服務端的路由來匹配url,當沒有匹配到路由的時候返回404,從而實現fallback


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM