vue-router路由模式詳解(小結(jié))
一、路由模式解析
要講vue-router的路由模式,首先要了解的一點(diǎn)就是路由是由多個(gè)URL組成的,使用不同的URL可以相應(yīng)的導(dǎo)航到不同的位置。
如果有進(jìn)行過服務(wù)器開發(fā)或者對http協(xié)議有所了解就會(huì)知道,瀏覽器中對頁面的訪問是無狀態(tài)的,所以我們在切換不同的頁面時(shí)都會(huì)重新進(jìn)行請求。而實(shí)際使用vue和vue-router開發(fā)就會(huì)明白,在切換頁面時(shí)是沒有重新進(jìn)行請求的,使用起來就好像頁面是有狀態(tài)的,這是什么原因呢。
這其實(shí)是借助了瀏覽器的History API來實(shí)現(xiàn)的,這樣可以使得頁面跳轉(zhuǎn)而不刷新,頁面的狀態(tài)就被維持在瀏覽器中了。
vue-router中默認(rèn)使用的是hash模式,也就是會(huì)出現(xiàn)如下的URL:,URL中帶有#號(hào)
我們可以用如下代碼修改成history模式:
import Vue from 'vue' import Router from 'vue-router' import Main from '@/components/Main' Vue.use(Router) export default new Router({ mode: 'history', routes: [ { path: '/', component: Main } ] })
這樣子URL中的#號(hào)就被去除了。
實(shí)際上存在三種模式:
Hash: 使用URL的hash值來作為路由。支持所有瀏覽器。
History: 以來HTML5 History API 和服務(wù)器配置。參考官網(wǎng)中HTML5 History模式
Abstract: 支持所有javascript運(yùn)行模式。如果發(fā)現(xiàn)沒有瀏覽器的API,路由會(huì)自動(dòng)強(qiáng)制進(jìn)入這個(gè)模式。
二、兩種模式的區(qū)別
1、hash模式
hash模式背后的原理是onhashchange
事件,可以在window
對象上監(jiān)聽這個(gè)事件:
window.onhashchange = function(event){ console.log(event.oldURL, event.newURL); let hash = location.hash.slice(1); document.body.style.color = hash; }
上面的代碼可以通過改變hash來改變頁面字體顏色,雖然沒什么用,但是一定程度上說明了原理。
更關(guān)鍵的一點(diǎn)是,因?yàn)閔ash發(fā)生變化的url都會(huì)被瀏覽器記錄下來,從而你會(huì)發(fā)現(xiàn)瀏覽器的前進(jìn)后退都可以用了,同時(shí)點(diǎn)擊后退時(shí),頁面字體顏色也會(huì)發(fā)生變化。這樣一來,盡管瀏覽器沒有請求服務(wù)器,但是頁面狀態(tài)和url一一關(guān)聯(lián)起來,后來人們給它起了一個(gè)霸氣的名字叫前端路由,成為了單頁應(yīng)用標(biāo)配。
我們寫個(gè)簡單的方法來測試一下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div>測試一下</div> <script type="text/javascript"> window.onhashchange = function(event){ console.log(event.oldURL,event.newURL) let hash = location.hash.slice(1); document.body.style.color = hash; } </script> </body> </html>
并且通過瀏覽器的前進(jìn)、后退頁面均可以變化。
網(wǎng)易云音樂,百度網(wǎng)盤就采用了hash路由,看起來就是這個(gè)樣子:
http://music.163.com/#/friend
https://pan.baidu.com/disk/home#list/vmode=list
2、history路由
隨著history api的到來,前端路由開始進(jìn)化了,前面的hashchange,你只能改變#后面的url片段,而history api則給了前端完全的自由
history api可以分為兩大部分:切換和修改
(1)切換歷史狀態(tài)
包括back、forward
、go
三個(gè)方法,對應(yīng)瀏覽器的前進(jìn),后退,跳轉(zhuǎn)操作,有同學(xué)說了,(谷歌)瀏覽器只有前進(jìn)和后退,沒有跳轉(zhuǎn),嗯,在前進(jìn)后退上長按鼠標(biāo),會(huì)出來所有當(dāng)前窗口的歷史記錄,從而可以跳轉(zhuǎn)(也許叫跳更合適):
history.go(-2);//后退兩次 history.go(2);//前進(jìn)兩次 history.back(); //后退 hsitory.forward(); //前進(jìn)
(2)修改歷史狀態(tài)
包括了pushState、replaceState
兩個(gè)方法,這兩個(gè)方法接收三個(gè)參數(shù):stateObj,title,url
history.pushState({color:'red'}, 'red', 'red') window.onpopstate = function(event){ console.log(event.state) if(event.state && event.state.color === 'red'){ document.body.style.color = 'red'; } } history.back(); history.forward();
通過pushstate把頁面的狀態(tài)保存在state對象中,當(dāng)頁面的url再變回這個(gè)url時(shí),可以通過event.state取到這個(gè)state對象,從而可以對頁面狀態(tài)進(jìn)行還原,這里的頁面狀態(tài)就是頁面字體顏色,其實(shí)滾動(dòng)條的位置,閱讀進(jìn)度,組件的開關(guān)的這些頁面狀態(tài)都可以存儲(chǔ)到state的里面。
通過history api,我們丟掉了丑陋的#,但是它也有個(gè)毛?。?/p>
不怕前進(jìn),不怕后退,就怕刷新,f5,(如果后端沒有準(zhǔn)備的話),因?yàn)樗⑿率菍?shí)實(shí)在在地去請求服務(wù)器的。
在hash模式下,前端路由修改的是#中的信息,而瀏覽器請求時(shí)是不帶它玩的,所以沒有問題。但是在history下,你可以自由的修改path,當(dāng)刷新時(shí),如果服務(wù)器中沒有相應(yīng)的響應(yīng)或者資源,會(huì)分分鐘刷出一個(gè)404來。
(3)popstate實(shí)現(xiàn)history路由攔截,監(jiān)聽頁面返回事件
當(dāng)活動(dòng)歷史記錄條目更改時(shí),將觸發(fā)popstate事件。
1、如果被激活的歷史記錄條目是通過對 history.pushState() 的調(diào)用創(chuàng)建的,或者受到對 history.replaceState() 的調(diào)用的影響,popstate事件的state屬性包含歷史條目的狀態(tài)對象的副本。
2、需要注意的是調(diào)用 history.pushState() 或 history.replaceState() 用來在瀏覽歷史中添加或修改記錄,不會(huì)觸發(fā)popstate事件;
只有在做出瀏覽器動(dòng)作時(shí),才會(huì)觸發(fā)該事件,如用戶點(diǎn)擊瀏覽器的回退按鈕(或者在Javascript代碼中調(diào)用history.back())
我們測試一下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div>測試一下</div> <script type="text/javascript"> if (window.history && window.history.pushState) { window.onpopstate = function(event) { console.log("location: " + document.location + ", state: " + JSON.stringify(event.state)); //window.history.go(1) //window.history.back() }; //window.addEventListener("popstate", function(e) { // window.location = 'http://www.baidu.com'; //}, false); !function() { var state = { title: "title", url: "#" }; window.history.pushState(state, "title", "#"); }(); } </script> </body> </html>
刷新時(shí)不打印,刷新多次,再后退,每次都有,直到為null
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vite+vue3項(xiàng)目初始化搭建的實(shí)現(xiàn)步驟
本文主要介紹了vite+vue3項(xiàng)目初始化搭建的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-07-07詳解為什么Vue中不要用index作為key(diff算法)
這篇文章主要介紹了詳解為什么Vue中不要用index作為key(diff算法),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04vue進(jìn)度條組件實(shí)現(xiàn)代碼(可拖拽可點(diǎn)擊)
在日常開發(fā)中隨著需求的個(gè)性化,邏輯的復(fù)雜化,自定義組件也變得越來越常見,這篇文章主要給大家介紹了關(guān)于vue進(jìn)度條組件實(shí)現(xiàn)(可拖拽可點(diǎn)擊)的相關(guān)資料,需要的朋友可以參考下2023-12-12使用vue3+TS實(shí)現(xiàn)簡易組件庫的全過程
當(dāng)市面上主流的組件庫不能滿足我們業(yè)務(wù)需求的時(shí)候,那么我們就有必要開發(fā)一套屬于自己團(tuán)隊(duì)的組件庫,下面這篇文章主要給大家介紹了如何使用vue3+TS實(shí)現(xiàn)簡易組件庫的相關(guān)資料,需要的朋友可以參考下2022-03-03vant steps流程圖的圖標(biāo)使用slot自定義方式
這篇文章主要介紹了vant steps流程圖的圖標(biāo)使用slot自定義方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06Vue生命周期activated之返回上一頁不重新請求數(shù)據(jù)操作
這篇文章主要介紹了Vue生命周期activated之返回上一頁不重新請求數(shù)據(jù)操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07使用vue實(shí)現(xiàn)一個(gè)電子簽名組件的示例代碼
這篇文章主要介紹了使用vue實(shí)現(xiàn)一個(gè)電子簽名組件的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01vue里的axios如何獲取本地json數(shù)據(jù)
這篇文章主要介紹了vue里的axios如何獲取本地json數(shù)據(jù),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08Vue3?計(jì)算屬性computed的實(shí)現(xiàn)原理
這篇文章主要介紹了Vue3?計(jì)算屬性computed的實(shí)現(xiàn)原理,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-08-08