在學習React Router時,看到有關History有以下描述:html
React Router 是創建在 history 之上的。 簡而言之,一個 history 知道如何去監聽瀏覽器地址欄的變化, 並解析這個 URL 轉化爲 location 對象, 而後 router 使用它匹配到路由,最後正確地渲染對應的組件。
這段描述看的暈暈的,history究竟是個什麼東西呢?這得從history API的出身提及。前端
咱們都知道一個URL表明了網絡上惟一的一個資源。這個資源能夠是一個頁面,一張圖片等等。在地址欄裏輸入一個url地址,瀏覽器就會將對應的資源展現出來。當在不一樣的地址之間跳轉時,咱們很天然地想要回退或者前進一個地址。爲了實現這個功能,瀏覽器廠商定義了history
對象。這時的history
對象大體有go()
、forward()
、back()
等方法,用於實現歷史記錄的訪問、跳轉。html5
使用 history API與瀏覽器歷史記錄進行交互
history
與 URL 就這樣和諧的相處了一段時間,直到ajax技術的興起。git
瀏覽器有一個限制:若是你改變了URL,甚至是經過腳本,它就得向服務器發送請求,刷新整個頁面。這很耗時,也耗資源,由於有時候2個頁面長得差很少,僅僅有一小塊地方不一樣。爲了解決這個問題,ajax
技術興起,利用ajax,能夠不改變URL,只向服務器請求須要變更的數據,而後在前端經過DOM操做實現頁面的局部更新。github
ajax
極大提升了頁面加載速度與用戶體驗。不過它同時帶來了一個問題:同一個URL地址,可能會展現不少不一樣的信息,那麼它做爲惟一資源標識符的這個定義,在這裏被破壞了。ajax
有沒有一個一箭雙鵰的辦法呢?既能夠實現頁面的局部更新,又可以改變地址欄裏的URL?瀏覽器
第一個跳出來解決問題的是URL中的#
。#
表明網頁中的一個位置。它右邊的字符就是頁面中的位置標識符。例以下面的URL:服務器
http://www.example.com/index.html#print
就表明網頁index.html的print位置。瀏覽器讀取這個URL後,會自動將print位置滾動至對應的區域。爲網頁位置指定標識符,有兩個方法。一是使用錨點,好比,二是使用id屬性,好比<div id="print" >網絡
#
的威力在於它是用來指導瀏覽器動做的,對服務器端徹底無用。因此,HTTP請求中不包括#
,改變#
不觸發網頁重載。所以,若是咱們在使用ajax局部刷新頁面時,同時改變URL#
後面的標識符,就實現了局部刷新+改變URL了。學習
事實上,早前的twitter、google就是這麼實現的。google甚至爲此專門定義了一個搜索引擎優化的標識符#!
。能夠參考這篇文章:URL的井號
URL畢竟是用於資源分享的,帶個#
總感受有點彆扭。若是不用#
,有沒有辦法可以修改URL,同時又不向服務器發送請求呢?這就輪到history對象再次登場了。在HTML5規範中,W3C對history對象進行了一波升級:
HTML5 history API包括2個方法:history.pushState()和history.replaceState(),以及1個事件:window.onpopstate。
利用這2個方法,能夠實現經過腳本修改瀏覽器中的URL地址,而不觸發頁面重載。採用這個方案,一個ajax請求過程是這樣的:
問題獲得解決。
在React Router中,將上述2個方案進行了整合,統一到了一個history庫中。也就是咱們看到的HashHistory
和BrowserHistory
。HashHistory
是上面井號方案的封裝,BrowserHistory
則是對History方案的封裝。特別須要注意到是,BrowserHistory須要對服務器端改造。
爲何?
考慮如下場景,咱們用React Router的BrowserHistory開發了一個單頁面應用,主頁地址以下:
http://www.mysite.com/index
在index中能夠點擊連接進入歡迎頁,詳細介紹頁等,地址爲:
http://www.mysite.com/index/welcome http://www.mysite.com/index/detail
若是咱們在瀏覽器裏直接輸入主頁面地址,而後經過頁面裏連接跳轉到二級頁面,通常是沒有問題的。可是,若是在瀏覽器裏直接輸入http://www.mysite.com/index/welcome
會發生什麼呢?
瀏覽器會認爲這是一個URL請求,向服務器端請求這個URL表明的資源。但咱們這是一個單頁面應用,服務端只有一個index.html頁面,沒有跟這個地址匹配的資源,頁面就會報錯了。
所以,咱們須要稍微改造一下服務端,將全部這樣的請求都指向index.html頁面,由前臺處理路由信息。
#
有話說:
爲嘛,長得醜就要被淘汰嗎!