前端路由實(shí)現(xiàn)

路由實(shí)現(xiàn)原理,就是根據(jù)不同的 url ,在頁面上顯示相應(yīng)的內(nèi)容。而瀏覽器 url 變化時(shí),會(huì)造成頁面的刷新。前端路由要解決問題就是,在改變 url 的情況下,保證頁面的不刷新。

hash

url 中的 hash 改變時(shí),瀏覽器不會(huì)向服務(wù)器發(fā)送請求,頁面不會(huì)刷新。

hash 應(yīng)用的常見場景如,用 hash 實(shí)現(xiàn)頁面導(dǎo)航。如下代碼,點(diǎn)擊 a 標(biāo)簽 '聯(lián)系'(a 標(biāo)簽的 href 屬性值為 #contact),瀏覽器 url 會(huì)變成http://www.xxx.com/#contact,頁面會(huì)定位到元素 idcontact 的位置。

<!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>

另外,urlhash 變化時(shí),會(huì)觸發(fā) hashchange 事件,該事件上有兩個(gè)屬性,oldURLnewURL,分別表示跳轉(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 可以實(shí)現(xiàn)無刷新更改地址欄鏈接,再配合 AJAX 即可實(shí)現(xiàn)頁面無刷新跳轉(zhuǎn)。具體實(shí)現(xiàn):當(dāng)用戶點(diǎn)擊導(dǎo)航鏈接 a 標(biāo)簽時(shí),通過 replaceState 將瀏覽器地址欄的 url 更改為 a 標(biāo)簽 href 屬性的值,同時(shí)配合 AJAX 獲取數(shù)據(jù),替換頁面 DOM 中的內(nèi)容。

history 作為一個(gè)全局變量(即 window.history),不繼承任何屬性,在 html4 標(biāo)準(zhǔn)中,history 有如下屬性和方法:

  • History.length 屬性: 返回一個(gè)整數(shù),該整數(shù)表示會(huì)話歷史中元素的數(shù)目,包括當(dāng)前加載的頁。例如,在一個(gè)新的選項(xiàng)卡加載的一個(gè)頁面中,這個(gè)屬性返回1。
  • History.back() 方法:前往上一頁, 用戶可點(diǎn)擊瀏覽器左上角的返回按鈕模擬此方法。等價(jià)于history.go(-1).
  • History.forward() 方法:在瀏覽器歷史記錄里前往下一頁,用戶可點(diǎn)擊瀏覽器左上角的前進(jìn)按鈕模擬此方法。等價(jià)于 history.go(1).
  • History.go() 方法:通過當(dāng)前頁面的相對位置從瀏覽器歷史記錄( 會(huì)話記錄 )加載頁面。比如:參數(shù)為-1的時(shí)候?yàn)樯弦豁?,參?shù)為1的時(shí)候?yàn)橄乱豁? 當(dāng)整數(shù)參數(shù)超出界限時(shí),那么這個(gè)方法沒有任何效果也不會(huì)報(bào)錯(cuò)。調(diào)用沒有參數(shù)的 go() 方法或者不是整數(shù)的參數(shù)時(shí)也沒有效果。

html5 標(biāo)準(zhǔn)中,history新增了 history.pushState(state, title, url)、history.replaceState(state, title, url) 方法,和 popstate 事件。

  • History.pushState(state, title [, url]) 方法:往瀏覽歷史堆棧的頂部添加一個(gè)狀態(tài),不刷新頁面。pushState() 帶有三個(gè)參數(shù):一個(gè)狀態(tài)對象,一個(gè)標(biāo)題(現(xiàn)在被忽略了),以及一個(gè)可選的URL地址。

    state 為一個(gè)對象或 null,它會(huì)在觸發(fā) window 的 popstate 事件(window.onpopstate)時(shí),作為參數(shù)的 state 屬性傳遞過去;如果你像 pushState() 方法傳遞了一個(gè)序列化表示大于 640k 的 state 對象,這個(gè)方法將扔出一個(gè)異常。如果你需要更多的空間,推薦使用 sessionStorage 或者 localStorage。title 為頁面的標(biāo)題,但當(dāng)前所有瀏覽器都忽略這個(gè)參數(shù)。URL 為頁面的 URL,不寫則為當(dāng)前頁;新 URL 必須和當(dāng)前URL在同一個(gè)源下;否則,pushState() 將丟出異常。

  • History.replaceState(state, title [, url]):更改當(dāng)前頁面的歷史記錄值,不刷新頁面。參數(shù)同上。這種更改并不會(huì)去訪問該URL。
  • **popstate ** 事件:當(dāng)活動(dòng)歷史記錄條目更改時(shí),將觸發(fā) popstate 事件。如果被激活的歷史記錄條目是通過對 history.pushState() 的調(diào)用創(chuàng)建的,或者受到對 history.replaceState() 的調(diào)用的影響,popstate 事件的 state 屬性包含歷史條目的狀態(tài)對象的副本。

    需要注意的是調(diào)用 history.pushState() 或history.replaceState() 不會(huì)觸發(fā) popstate 事件。只有在做出瀏覽器動(dòng)作時(shí),才會(huì)觸發(fā)該事件,如用戶點(diǎn)擊瀏覽器的回退按鈕。

    當(dāng)我們需要監(jiān)聽該事件并作出相應(yīng)響應(yīng)時(shí),我們應(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/

【4】https://developer.mozilla.org/zh-CN/docs/Web/API/History

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容