前端路由hash、history模式的區別及簡單實現
阿新 • • 發佈:2020-12-16
技術標籤:Javascript前端javascripthtml5vue.js
一、什麼是路由?
路由是根據不同的url地址來顯示不同的頁面或內容。
當我們訪問一個url地址的時候,大致流程可以想象成這樣:
- 瀏覽器向伺服器發出請求;
- 伺服器監聽到80埠,如果有請求,那麼就解析url地址。
- 伺服器根據路由配置,然後就返回相應的資訊(比如html字串、json資料或圖片等)。
- 瀏覽器根據伺服器響應的Content-Type來決定如何解析資料。
以上就是傳統路由最初始的實現方式,缺點是每次路由切換都需要重新整理頁面,發ajax請求,然後把資料返回回來,這樣對使用者體驗就不好了。
因此為了提升使用者體驗,前端路由就產生了,它就可以解決瀏覽器不會重新重新整理了。
在瞭解路由之前,先簡單的看一下history api有哪些方法:
> window.history.length: 返回當前會話瀏覽的頁面數量; > window.history.go(): 接收一個整數作為引數,按照當前頁面在會話瀏覽歷史記錄中的位置進行移動; > window.history.back(): 移動到上一頁。相當於點選瀏覽器的後退按鈕; > window.history.forward(): 移動到下一頁,相當於點選瀏覽器的前進按鈕; > window.history.pushState(): 在會話瀏覽歷史記錄中新增一條記錄; > window.history.replaceState(): 該方法用法和history.pushState方法類似,但是該方法的含義是將修改會話瀏覽歷史的當前記錄,而不是新增一條記錄。
有了這些基本知識後,我們再來看下前端路由,前端路由也有2種模式,第一種是hash模式,第二種是history模式。我們來分別看下這兩種知識點及區別如下:
二、hash模式
hash路由模式是這樣的:http://xxx.com/#/xx。 帶#號,後面就是hash值的變化。實現hash路由的基本條件:
- url中hash值的改變,並不會重新載入頁面;
- hash值的改變會在瀏覽器的訪問歷史中增加一條記錄,可以通過瀏覽器的後退,前進按鈕控制hash值的切換;
- 可以通過hashchange事件,監聽到hash值的變化,從而載入不同的頁面顯示。
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>hash test</title>
</head>
<body>
<p>hash test</p>
<button id="btn">修改 hash</button>
<script>
// hash 變化,包括:
// a. JS 修改 url
// b. 手動修改 url 的 hash
// c. 瀏覽器前進、後退
window.onhashchange = (event) => {
console.log('old url', event.oldURL)
console.log('new url', event.newURL)
console.log('hash:', location.hash)
}
// 頁面初次載入,獲取 hash
// 當初始的 HTML 文件被完全載入和解析完成之後,DOMContentLoaded 事件被觸發
document.addEventListener('DOMContentLoaded', () => {
console.log('hash:', location.hash)
})
// JS 修改 url
document.getElementById('btn').addEventListener('click', () => {
location.href = '#/user'
})
</script>
</body>
</html>
三、history模式
- 用url規範的路由,但跳轉時不重新整理頁面;
- window.history.pushState 能修改路徑、查詢引數和片段識別符號。pushState比hash更符合前端路由的訪問方式,更加優雅(因為不帶#號);
- window.onpopstate來監聽歷史棧的改變,只要歷史棧有資訊發生改變的話,就會觸發該事件。
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>history API test</title>
</head>
<body>
<p>history API test</p>
<button id="btn">修改 url</button>
<script>
// 頁面初次載入,獲取 path
document.addEventListener('DOMContentLoaded', () => {
console.log('load', location.pathname)
})
// 開啟一個新的路由
// 【注意】用 pushState 方式,瀏覽器不會重新整理頁面
document.getElementById('btn').addEventListener('click', () => {
const state = { name: 'page1' }
console.log('切換路由到', 'page1')
history.pushState(state, '', 'page1') // 重要!!!
})
// 監聽瀏覽器前進、後退
window.onpopstate = (event) => { // 重要!!!
console.log('onpopstate', event.state, location.pathname)
}
</script>
</body>
</html>
需要 server 端配合,可參考
https://router.vuejs.org/zh/guide/essentials/history-mode.html#%E5%90%8E%E7%AB%AF%E9%85%8D%E7%BD%AE%E4%BE%8B%E5%AD%90
四、總結
傳統的路由指的是:當用戶訪問一個url時,對應的伺服器會接收這個請求,然後解析url中的路徑,從而執行對應的處理邏輯。這樣就完成了一次路由分發。
而前端路由是不涉及伺服器的,是前端利用hash或者HTML5的history API來實現的,一般用於不同內容的展示和切換。