浏览器-路由的模式
前言:
路由這概念最開始是在后端出現(xiàn)的,在前后端不分離的時候,由后端來控制路由,服務器接收客戶端的請求,解析對應的url路徑,并返回對應的頁面/資源。簡單的說,路由就是根據(jù)不同的url地址來展示不同的內(nèi)容或頁面。
現(xiàn)在的網(wǎng)絡應用程序越來越多的使用AJAX異步請求完成頁面的無縫刷新,雖然Ajax解決了用戶交互時體驗的痛點,但是多頁面之間的跳轉一樣會有不好的體驗,所以便有了spa(single-page application)使用的誕生。而spa應用便是基于前端路由實現(xiàn)的,所以便有了前端路由。
路由的實現(xiàn)方式:
路由需要實現(xiàn)三個功能:
- 當瀏覽器地址變化時,切換頁面;
- 點擊瀏覽器【后退】、【前進】按鈕,網(wǎng)頁內(nèi)容跟隨變化;
- 刷新瀏覽器,網(wǎng)頁加載當前路由對應內(nèi)容;
在單頁面web網(wǎng)頁中, 單純的瀏覽器地址改變, 網(wǎng)頁不會重載,如單純的hash網(wǎng)址改變網(wǎng)頁不會變化,因此我們的路由主要是通過監(jiān)聽事件,并利用js實現(xiàn)動態(tài)改變網(wǎng)頁內(nèi)容,有兩種實現(xiàn)方式:
- hash模式:監(jiān)聽瀏覽器地址hash值變化,執(zhí)行相應的js切換網(wǎng)頁;
- history模式:利用history API實現(xiàn)url地址改變,網(wǎng)頁內(nèi)容改變;
兩者之間的區(qū)別就是hash會在瀏覽器地址后面增加#號,而history可以自定義地址。
路由的實現(xiàn):
hash模式:
早期的前端路由的實現(xiàn)就是基于location.hash來實現(xiàn)的。其實現(xiàn)原理也很簡單:
hash的幾個特性:
- hash指的是地址中#號以及后面的字符,也稱為散列值。hash也稱作錨點,本身是用來做頁面跳轉定位的。
- 散列值是不會隨請求發(fā)送到服務器端的,所以改變hash,不會重新加載頁面。
- 監(jiān)聽 window 的 hashchange 事件,當散列值改變時,可以通過 location.hash 來獲取和設置hash值。
- hash值的改變,都會在瀏覽器的訪問歷史中增加一個記錄。因此我們能通過瀏覽器的回退、前進按鈕控制hash的切換。
- location.hash值的變化會直接反應到瀏覽器地址欄。
hash的改變方式:
使用window.location.hash屬性及窗口的onhashchange事件,可以實現(xiàn)監(jiān)聽瀏覽器地址hash值變化,執(zhí)行相應的js切換網(wǎng)頁。
- 通過a標簽,并設置href屬性,當用戶點擊這個標簽后,URL就會發(fā)生改變,從而觸發(fā)hashchange事件。
- 直接使用JavaScript來對loaction.hash進行賦值,從而改變URL,觸發(fā)hashchange事件。
- 直接通過輸入url鏈接或者修改鏈接進行跳轉。
大概的流程:
history模式:
hash雖然也很不錯,但使用時都需要加上#,并不是很美觀,因此HTML5又提供了History API來實現(xiàn)URL的變化。
- window.history 屬性指向 History 對象,它表示當前窗口的瀏覽歷史。當發(fā)生改變時,只會改變頁面的路徑,不會刷新頁面。
- History 對象保存了當前窗口訪問過的所有頁面網(wǎng)址。通過 history.length 可以得出當前窗口瀏覽網(wǎng)址的記錄。
- 由于安全原因,瀏覽器不允許腳本讀取這些地址,但是允許在地址之間導航。
- 瀏覽器工具欄的“前進”和“后退”按鈕,其實就是對 History 對象進行操作。
主要屬性:
- History.length:當前窗口訪問過的網(wǎng)址數(shù)量(包括當前網(wǎng)頁)
- History.state:History 堆棧最上層的狀態(tài)值
主要的API:
- History.back():移動到上一個網(wǎng)址,等同于點擊瀏覽器的后退鍵。對于第一個訪問的網(wǎng)址,該方法無效果。
- History.forward():移動到下一個網(wǎng)址,等同于點擊瀏覽器的前進鍵。對于最后一個訪問的網(wǎng)址,該方法無效果。
- History.go():接受一個整數(shù)作為參數(shù),以當前網(wǎng)址為基準,移動到參數(shù)指定的網(wǎng)址。如果參數(shù)超過實際存在的網(wǎng)址范圍,該方法無效果;如果不指定參數(shù),默認參數(shù)為0,相當于刷新當前頁面。
- History.pushState():用于在歷史中添加一條記錄。pushState()方法不會觸發(fā)頁面刷新,只是導致 History 對象發(fā)生變化,地址欄會有變化。
- History.replaceState():用來修改 History 對象的當前記錄,用法與 pushState() 方法一樣。
history的幾個特性:
- 狀態(tài)對象(state object):一個JavaScript對象,與用pushState()方法創(chuàng)建的新歷史記錄條目關聯(lián)。無論何時用戶導航到新創(chuàng)建的狀態(tài),都會觸發(fā)popstate事件,并能在事件中使用該對象。
- 標題(title):一般瀏覽器會忽略,最好傳入null。
- 地址(URL):就是需要新增的歷史記錄的地址,瀏覽器不會去直接加載改地址,但后面也可能會去嘗試加載該地址。此外需要注意的是,傳入的URL與當前URL應該是同源的。
popstate 事件:
每當 history 對象出現(xiàn)變化時,就會觸發(fā) popstate 事件。
注意:
- 僅僅調用pushState()方法或replaceState()方法 ,并不會觸發(fā)該事件。
- 只有用戶點擊瀏覽器倒退按鈕和前進按鈕,或者使用 JavaScript 調用History.back()、History.forward()、History.go()方法時才會觸發(fā)。
- 該事件只針對同一個文檔,如果瀏覽歷史的切換,導致加載不同的文檔,該事件也不會觸發(fā)。
- 頁面第一次加載的時候,瀏覽器不會觸發(fā)popstate事件。
大概的流程:
總結
- 上一篇: 史上最全测试流程详解----超详细
- 下一篇: Web前端之CSS(2)——框