理解瀏覽器的歷史記錄

這是一篇基礎文章,講述一些瀏覽器裏面歷史記錄棧管理的相關內容。寫這個的原由,源於我最近想研究pushState,看看用它來實現SPA會遇到哪些問題,而pushState最終影響的就是瀏覽器歷史記錄棧裏面的內容,因此就花了點時間琢磨了一下瀏覽器是如何管理歷史記錄棧的。由於在研究的過程當中,發現了一些曾經未曾注意到一些要點,因此就記錄下來了。html

demo地址:http://liuyunzhuge.github.io/blog/history/demo1.htmlgit

這個demo用於進行本文後面內容涉及到的相關測試,假如你也感興趣的話,建議每次要測試一個新的問題時,都在新選項卡里面打開這個demo,而不是從一個已經打開過網頁的選項卡里面打開;由於已經打開過網頁的選項卡,它的歷史記錄棧裏面已經包含了以前訪問的網頁記錄,因此會對你要測試的問題結果產生影響。github

瀏覽器會對同一個窗口(選項卡)中訪問的網頁進行記錄,無論咱們是經過如下哪一種方式改變網頁,瀏覽器都會把改變後的網頁記錄下來,以便經過瀏覽器的前進和後退按鈕,可以快速的切換到已經訪問過的網頁:
1)直接在地址欄輸入網頁地址;
2)經過網頁內的超連接點擊,跳轉到其它網頁;可是不能是在新窗口中打開的連接;
3)經過腳本改變location.href跳轉到其它網頁;
4)經過表單提交跳轉到其它網頁;可是不能是提交到新窗口的表單。
總之,只要是在同一個窗口內,網頁發生了跳轉,瀏覽器都會記錄。不過刷新除外,history對象的length屬性能夠查看當前窗口存儲的歷史記錄總數,在前面的demo頁面中,我把這個屬性打印在頁面上,只有網頁改變的時候,這個屬性纔會變化;而刷新網頁不會改變這個屬性。chrome

瀏覽器有一個數據結構來存儲網頁的歷史記錄,我把它稱之爲歷史記錄棧,由於它的結構跟棧的使用方式有些類似。瀏覽器

操做測試一:假如你複製前面的demo地址,而後在chrome瀏覽器下按如下步驟進行操做:數據結構

打開新選項卡;輸入demo1.html;點擊demo2.html;點擊demo3.html;點擊demo4.html;點擊demo3.html;點擊demo2.html;點擊demo1.html。測試

瀏覽器會如下圖相似的方式來存儲以上的訪問記錄:firefox

image

因爲如今的瀏覽器都是多選項卡的模式,當你打開一個選項卡的時候,即便沒有訪問具體網頁,瀏覽器也爲這個選項卡建立好了BOM對象,好比history對象,而後把新選項卡的空白頁做爲歷史記錄裏面的第一條記錄。因此在上圖中的最後一列能夠看到8條記錄,跟demo頁面裏顯示的數字同樣:3d

image

跟歷史記錄棧一塊兒的,瀏覽器還有一個訪問指針來表示當前網頁在歷史記錄棧中的位置。默認狀況下,當咱們經過前面列舉的方式改變網頁地址的時候,都會把新的頁面壓入到歷史記錄棧的頂部,同時把指針指向到這個最新的網頁,就如上面的圖中所示,每次改變了頁面,當前頁面的指針始終指向的是歷史記錄棧最頂部的那條記錄;當咱們經過瀏覽器的前進後退功能(包括按鈕,快捷,右鍵菜單等方式)或者是history提供的go/back/forward方法,都不會改變歷史記錄棧的內容,只會移動一下這個指針:指針

1)前進功能/go(1)/forward,只是讓這個指針上移1個位置;

2)後退功能/go(-1)/forward,只是讓這個指針下移1個位置;

3)go(n)讓指針上移n個位置;go(-n)讓指針下移n個位置。

瀏覽器根據移動後的指針位置,找到歷史記錄棧中的網頁進行顯示。假如接着操做測試一的結果,繼續作如下操做。

操做測試二:點擊7次瀏覽器後退按鈕。

瀏覽器此時歷史記錄棧的存儲狀況就變成下面這個狀態了:

image

雖然history.go(n)和history.go(-n)能夠將指針移動到任意位置,可是當要移動到的位置超出了歷史記錄棧的位置範圍時,指針就不會移動。因此在操做測試二的結果中,調用history.go(-100)和history.go(100)都是不會起做用的。

還有兩種狀況會改變歷史記錄棧的內容。

操做測試三:假如咱們接着操做測試二的結果,點擊三次前進按鈕,讓瀏覽器的歷史記錄棧進入到下面這個狀態:

image

此時因爲操做測試二和操做測試三都沒有改變歷史記錄棧的內容,因此正確的話,頁面上的歷史記錄統計應該仍是8:

image

操做測試四:接着,咱們作如下兩步操做:點擊demo2.html,點擊demo3.html。這個時候頁面上的歷史記錄統計變成了:

image

history.length已經改變了,說明歷史記錄棧的內容也變化了。只不過爲何變成6,而不是10(8+2)呢?看看此時瀏覽器歷史記錄棧的狀態:

image

瀏覽器在往歷史記錄棧裏面壓入新的記錄時,是直接在當前指針後面壓入的,若是當前指針的後面,還有其它的記錄項,都會被丟棄掉。這樣就好理解爲啥操做測試四以後的歷史記錄總數只有6個了。

瀏覽器對歷史記錄的管理還有一個要點就是對歷史記錄棧的存儲總數有限制,chrome和firefox都是50。當歷史記錄棧的存儲的量超出這個限制後,歷史記錄的存儲就會採起滾動的方式存儲,也就是新的記錄會壓入到棧的頂部,最底部的記錄會從棧的底部移除出去。經過在demo頁面裏,不斷地切換點擊demo1,demo2,demo3,demo4,當達到必定次數的時候,頁面打印的統計信息再也不變化,就表示達到歷史記錄達到限制了。不過IE11,我點到100多,發現它還在變化,說明IE的限制可能更高,也可能沒有。。

本文記錄了一些瀏覽器關於歷史記錄管理的內容,可能有分析不到位的地方,歡迎你們的批評與指正。以上內容但願對有須要的朋友加深對history以及pushState的理解有所幫助,謝謝閱讀:)


補充於2016-10-12:

網頁錨點的變化,也會致使歷史記錄棧的更新,特性與前文描述相同。

相關文章
相關標籤/搜索