官术网_书友最值得收藏!

1.2.1 history.pushState

1.基本用法

history.pushState方法作為HTML5特性的一部分,目前被廣泛使用。history.pushState用于無刷新增加歷史棧記錄,調用history.pushState方法可改變?yōu)g覽器路徑。

history.pushState方法需要3個參數(shù):狀態(tài)對象、標題(目前被忽略)和可選的URL。其語法格式為

當設置第三個參數(shù)URL時,可改變?yōu)g覽器的URL,且不會刷新瀏覽器。

如果URL中包含Unicode字符,則瀏覽器也會將字符按UTF-8編碼。

雖然在瀏覽器地址欄中顯示的還是中文字符串,但實際上代碼得到的是已經編碼過的字符串。

除設置第三個參數(shù)為字符串外,在筆者測試的Chrome 77版本中同樣支持傳入URL對象。

history.pushState方法的第一個參數(shù)為需要傳入的狀態(tài),狀態(tài)的類型可以為可實施結構化拷貝算法的任意類型。在設置了第一個參數(shù)后,可通過history.state讀取。

因為歷史棧由瀏覽器統(tǒng)一管理,不屬于某個具體頁面,并不存在于頁面的內存中,所以歷史棧在刷新頁面后不會丟失,棧中記錄的各state對象也為持久化存儲,在導航過程中也不會丟失。

history.pushState使用結構化拷貝算法進行序列化存儲,會將拷貝后的結果記錄在歷史棧的記錄中。結構化拷貝算法除了能拷貝基本類型,還能拷貝更多的對象類型。相比JSON的序列化,這樣的序列化手段更為安全,如循環(huán)引用的對象,結構化序列的手段將會序列化成功,而JSON的序列化將會報錯,原因在于結構化序列的手段保存了每一個訪問過的對象的記錄,遇到復制過的對象會進行跳過。對此感興趣的讀者可以參考學習lodash的cloneDeep方法。結構化拷貝算法要注意特殊場景,如果history.pushState的state對象中有dom節(jié)點、error對象、function函數(shù)等,則調用history.pushState方法會拋出異常,且對某些對象的特定屬性,如regExp的lastIndex、object對象的setter和getter等,結構化拷貝的過程都會丟失。

結構化克隆算法是由HTML5規(guī)范定義的用于序列化復雜JavaScript對象的一個新算法。它比JSON更有能力,因為它支持包含循環(huán)圖的對象的序列化——對象中包含循環(huán)引用。此外,在某些情況下,結構化克隆算法可能比JSON更高效。

注意,history.pushState的第一個參數(shù)state,在Firefox中有大小限制,超過640KB的對象將會拋出異常。history.pushState的第三個參數(shù)URL出于安全考慮,需要同源的URL,例如,當前瀏覽器的域名為https://www.github.com,若history.pushState的URL為https://stackoverflow.com,則瀏覽器會拋出Uncaught DOMException異常。

2.歷史棧變化

history.pushState的調用會引起歷史棧的變化,瀏覽器通常會維護一個用戶訪問過的歷史棧,以便用戶進行導航。用戶通常通過單擊瀏覽器的“前進”和“后退”按鈕或者調用window.history.go等方法在歷史棧中進行移動,可理解為如圖1-1所示的虛線所表示的棧指針,不改變歷史棧的內容,棧內的記錄數(shù)量不會發(fā)生變化。

圖1-1 history.pushState添加歷史棧

而當調用history.pushState方法時,歷史棧的內容會被修改,行為表現(xiàn)為添加歷史棧的棧記錄,同時也會改變指針指向。如圖1-1所示,若當前的路徑地址為/b,當前的棧指針也指向/b的位置,在調用history.pushState({a:3},null,'/c')方法后,則棧記錄加1,棧指針也指向最新的棧記錄位置。

同時,要注意,如果當前棧指針不在棧頂,如當前棧的數(shù)量為3,單擊瀏覽器的“后退”按鈕,使得棧指針指向棧底后,再次調用history.pushState({a:4},null,'/d')方法,不僅會改變棧指針指向,而且會更新棧的內容,如圖1-2所示。

圖1-2 非棧頂情況history.pushState更新棧的內容

history.pushState會在當前指針所指的棧記錄后一個位置添加新的歷史記錄,并使之成為新的棧頂。

注意,這里減少了棧的記錄數(shù)量,棧記錄數(shù)從3變?yōu)?,地址/d成了新的棧頂。

如果不傳入第三個參數(shù)URL,則瀏覽器的地址欄不會發(fā)生變化,但是加入一個歷史棧,history.length就會發(fā)生相應的變化。

主站蜘蛛池模板: 临沭县| 黑龙江省| 安阳市| 宜兰市| 资中县| 闻喜县| 宁都县| 铜川市| 霍山县| 庆阳市| 商都县| 会东县| 双辽市| 景德镇市| 北票市| 漠河县| 东城区| 白山市| 东丰县| 南汇区| 齐河县| 淮北市| 神农架林区| 突泉县| 行唐县| 乌拉特前旗| 新野县| 炉霍县| 蒲城县| 平阴县| 平山县| 察雅县| 静宁县| 新竹市| 西畴县| 个旧市| 抚州市| 伽师县| 青神县| 屏南县| 乌兰察布市|