早期的路由都是後端實現的,直接根據 url
來 reload 頁面,頁面變得愈來愈複雜服務器端壓力變大,隨着 ajax
的出現,頁面實現非 reload 就能刷新數據,也給前端路由的出現奠基了基礎。咱們能夠經過記錄 url
來記錄 ajax
的變化,從而實現前端路由。前端
router
url
History
hash
react
你們能夠查看MDN的文檔:https://developer.mozilla.org/en-US/docs/Web/API/History
本文主要說兩個新增的API history.pushState
和 history.replaceState
(相同之處: 都會操做瀏覽器的歷史記錄,而不會引發頁面的刷新。
不一樣之處: pushState會增長一條新的歷史記錄,而replaceState則會替換當前的歷史記錄。)ajax
這兩個 API 都接收三個參數,分別是狀態對象(state) — 不管什麼時候用戶導航到新建立的狀態,popstate
事件都會被觸發,而且事件對象的state
屬性都包含歷史記錄條目的狀態對象的拷貝,默認null。後端
標題(title) — 標明將要進入的狀態,默認null。瀏覽器
地址(URL) — 新的歷史記錄條目的地址,傳入的URL與當前URL應該是同源的,不然,pushState()會拋出異常。默認爲當前URL。服務器
咱們在百度的控制檯輸入react-router
window.history.pushState(null, null, "https://www.baidu.com/?name=zzz")
此時url變成了這樣框架
狀態對象(state) — 不管什麼時候用戶導航到新建立的狀態,popstate
事件都會被觸發,而且事件對象的state
屬性都包含歷史記錄條目的狀態對象的拷貝,默認null。url
標題(title) — 標明將要進入的狀態,默認null。spa
地址(URL) — 新的歷史記錄條目的地址,傳入的URL與當前URL應該是同源的,不然,pushState()會拋出異常。默認爲當前URL。
咱們在百度的控制檯輸入
window.history.pushState(null, null, "https://www.baidu.com/?name=zzz")
此時url變成了這樣
每次改變 url 頁面並無刷新,一樣根據上文所述,瀏覽器會產生歷史記錄。這就是實現頁面無刷新狀況下改變 url 的前提,下面咱們說下第一個參數 狀態對象
若是運行 history.pushState() 方法,歷史棧對應的紀錄就會存入 狀態對象,咱們能夠隨時主動調用歷史條目。因此此時執行history.go(-1),就能夠回到上一個狀態(就是使url變成https://www.baidu.com/?name=zzz以前的狀態)
官方文檔提供了 popstate
事件,當咱們在歷史記錄中切換時就會產生 popstate
事件。對於觸發 popstate
事件的方式,各瀏覽器實現也有差別,咱們能夠根據不一樣瀏覽器作兼容處理。
咱們常常在 url
中看到 #
,這個 #
有兩種狀況,一個是咱們所謂的錨點,好比典型的回到頂部按鈕原理、Github
上各個標題之間的跳轉等,路由裏的 #
不叫錨點,咱們稱之爲 hash
,大型框架的路由系統大多都是哈希實現的。
基於hash的前端路由優勢是:能兼容低版本的瀏覽器
以 hash 形式(也可使用 History API 來處理)爲例,當 url 的 hash 發生變化時,觸發 hashchange 註冊的回調,回調中去進行不一樣的操做。
react-router
的底層原理就是依賴了history
,後文將介紹實現原理。