路由實現(xiàn)原理谬运,就是根據(jù)不同的 url
隙赁,在頁面上顯示相應(yīng)的內(nèi)容。而瀏覽器 url
變化時梆暖,會造成頁面的刷新伞访。前端路由要解決問題就是,在改變 url
的情況下式廷,保證頁面的不刷新咐扭。
hash
url
中的 hash
改變時,瀏覽器不會向服務(wù)器發(fā)送請求滑废,頁面不會刷新蝗肪。
hash
應(yīng)用的常見場景如,用 hash
實現(xiàn)頁面導(dǎo)航蠕趁。如下代碼薛闪,點擊 a
標(biāo)簽 '聯(lián)系'(a
標(biāo)簽的 href
屬性值為 #contact
),瀏覽器 url
會變成http://www.xxx.com/#contact
俺陋,頁面會定位到元素 id
為 contact
的位置豁延。
<!DOCTYPE html>
<html>
<head>
<style>
.nav li{
float: left;
}
article{
height: 600px;
text-align: center;
border: 1px solid black;
}
</style>
</head>
<body>
<ul class="nav">
<li><a href="#home">首頁</a></li>
<li><a href="#about">關(guān)于</a></li>
<li><a href="#work">作品</a></li>
<li><a href="#contact">聯(lián)系</a></li>
</ul>
<artice>
<section id="home">首頁</section>
<section id="about">關(guān)于</section>
<section id="work">作品</section>
<section id="contact">聯(lián)系</section>
</artice>
</body>
</html>
另外,url
的 hash
變化時腊状,會觸發(fā) hashchange
事件诱咏,該事件上有兩個屬性,oldURL
和 newURL
缴挖,分別表示跳轉(zhuǎn)前的 url
和跳轉(zhuǎn)后的 url
袋狞。通過分析 event.newURL
字段,配合 AJAX 發(fā)送請求映屋,即可讓頁面展示相對應(yīng)的內(nèi)容苟鸯。
window.addEventListener('hashchange', function(event) {
console.log('Hash changed from ' + event.oldURL);
console.log('Hash changed to ' + event.newURL);
});
history api
html5 的 history api 可以實現(xiàn)無刷新更改地址欄鏈接,再配合 AJAX 即可實現(xiàn)頁面無刷新跳轉(zhuǎn)棚点。具體實現(xiàn):當(dāng)用戶點擊導(dǎo)航鏈接 a 標(biāo)簽時早处,通過 replaceState
將瀏覽器地址欄的 url 更改為 a 標(biāo)簽 href 屬性的值,同時配合 AJAX 獲取數(shù)據(jù)瘫析,替換頁面 DOM 中的內(nèi)容砌梆。
history 作為一個全局變量(即 window.history)默责,不繼承任何屬性,在 html4 標(biāo)準(zhǔn)中么库,history 有如下屬性和方法:
- History.length 屬性: 返回一個整數(shù)傻丝,該整數(shù)表示會話歷史中元素的數(shù)目甘有,包括當(dāng)前加載的頁诉儒。例如,在一個新的選項卡加載的一個頁面中亏掀,這個屬性返回1忱反。
- History.back() 方法:前往上一頁, 用戶可點擊瀏覽器左上角的返回按鈕模擬此方法。等價于history.go(-1).
- History.forward() 方法:在瀏覽器歷史記錄里前往下一頁滤愕,用戶可點擊瀏覽器左上角的前進(jìn)按鈕模擬此方法温算。等價于 history.go(1).
- History.go() 方法:通過當(dāng)前頁面的相對位置從瀏覽器歷史記錄( 會話記錄 )加載頁面。比如:參數(shù)為-1的時候為上一頁间影,參數(shù)為1的時候為下一頁. 當(dāng)整數(shù)參數(shù)超出界限時医寿,那么這個方法沒有任何效果也不會報錯脚祟。調(diào)用沒有參數(shù)的 go() 方法或者不是整數(shù)的參數(shù)時也沒有效果。
html5 標(biāo)準(zhǔn)中,history新增了 history.pushState(state, title, url)
扩劝、history.replaceState(state, title, url)
方法,和 popstate
事件粗井。
History.pushState(state, title [, url]) 方法:往瀏覽歷史堆棧的頂部添加一個狀態(tài)枝哄,不刷新頁面。pushState() 帶有三個參數(shù):一個狀態(tài)對象键科,一個標(biāo)題(現(xiàn)在被忽略了)闻丑,以及一個可選的URL地址。
state 為一個對象或 null勋颖,它會在觸發(fā) window 的 popstate 事件(window.onpopstate)時嗦嗡,作為參數(shù)的 state 屬性傳遞過去;如果你像 pushState() 方法傳遞了一個序列化表示大于 640k 的 state 對象饭玲,這個方法將扔出一個異常侥祭。如果你需要更多的空間,推薦使用 sessionStorage 或者 localStorage咱枉。title 為頁面的標(biāo)題卑硫,但當(dāng)前所有瀏覽器都忽略這個參數(shù)。URL 為頁面的 URL蚕断,不寫則為當(dāng)前頁欢伏;新 URL 必須和當(dāng)前URL在同一個源下;否則亿乳,pushState() 將丟出異常硝拧。
- History.replaceState(state, title [, url]):更改當(dāng)前頁面的歷史記錄值径筏,不刷新頁面。參數(shù)同上障陶。這種更改并不會去訪問該URL滋恬。
**popstate ** 事件:當(dāng)活動歷史記錄條目更改時,將觸發(fā) popstate 事件抱究。如果被激活的歷史記錄條目是通過對 history.pushState() 的調(diào)用創(chuàng)建的恢氯,或者受到對 history.replaceState() 的調(diào)用的影響,popstate 事件的 state 屬性包含歷史條目的狀態(tài)對象的副本鼓寺。
需要注意的是調(diào)用 history.pushState() 或history.replaceState() 不會觸發(fā) popstate 事件勋拟。只有在做出瀏覽器動作時,才會觸發(fā)該事件妈候,如用戶點擊瀏覽器的回退按鈕敢靡。
當(dāng)我們需要監(jiān)聽該事件并作出相應(yīng)響應(yīng)時,我們應(yīng)該這樣組織代碼:
window.addEventListener("popstate", function(e) {
var state = e.state;
// do something...
});
【1】https://juejin.im/post/5aebc4a26fb9a07acc11924d
【2】https://www.renfei.org/blog/html5-introduction-3-history-api.html
【3】https://hijiangtao.github.io/2017/08/20/History-API-and-Location-Object/