vue-router路由原理

Vue-router路由原理

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

  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對象具體的類別執行不一樣操做vue

HashHistory

Hash(‘#’)符號的原本做用是加在URL指示網頁中的位置,#自己以及它後面的字符稱之爲hash,經過window.location.hash屬性來獲取node

Hash雖然出如今url中,但不會被包括在http請求中,它是用來指導瀏覽器動做的,對服務端徹底無用,所以改變hash不會從新加載頁面,若是是手動在url添加hash,這時能夠爲hash的改變添加監聽事件ajax

Window.addEventListener(‘hashchange’,funcRef,false)vue-router

每一次改變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

相關文章
相關標籤/搜索