- 深入理解React Router:從原理到實踐
- 李楊韜
- 1289字
- 2021-04-16 16:10:34
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ā)生相應的變化。

- PHP動態(tài)網站程序設計
- Monkey Game Development:Beginner's Guide
- Practical UX Design
- 薛定宇教授大講堂(卷Ⅳ):MATLAB最優(yōu)化計算
- Oracle Database 12c Security Cookbook
- 微信公眾平臺開發(fā):從零基礎到ThinkPHP5高性能框架實踐
- Android Wear Projects
- Python從入門到精通(第3版)
- Lift Application Development Cookbook
- 人工智能算法(卷1):基礎算法
- 計算機程序的構造和解釋(JavaScript版)
- JavaScript程序設計實例教程(第2版)
- Computer Vision with Python 3
- 程序員的算法趣題2
- Learning SaltStack(Second Edition)