# History 對象
## 概述
`window.history`屬性指向 History 對象,它表示當前窗口的瀏覽歷史。
History 對象保存了當前窗口訪問過的所有頁面網址。下面代碼表示當前窗口一共訪問過3個網址。
```javascript
window.history.length // 3
```
由于安全原因,瀏覽器不允許腳本讀取這些地址,但是允許在地址之間導航。
```javascript
// 后退到前一個網址
history.back()
// 等同于
history.go(-1)
```
瀏覽器工具欄的“前進”和“后退”按鈕,其實就是對 History 對象進行操作。
## 屬性
History 對象主要有兩個屬性。
- `History.length`:當前窗口訪問過的網址數量(包括當前網頁)
- `History.state`:History 堆棧最上層的狀態值(詳見下文)
```javascript
// 當前窗口訪問過多少個網頁
window.history.length // 1
// History 對象的當前狀態
// 通常是 undefined,即未設置
window.history.state // undefined
```
## 方法
### History.back()、History.forward()、History.go()
這三個方法用于在歷史之中移動。
- `History.back()`:移動到上一個網址,等同于點擊瀏覽器的后退鍵。對于第一個訪問的網址,該方法無效果。
- `History.forward()`:移動到下一個網址,等同于點擊瀏覽器的前進鍵。對于最后一個訪問的網址,該方法無效果。
- `History.go()`:接受一個整數作為參數,以當前網址為基準,移動到參數指定的網址,比如`go(1)`相當于`forward()`,`go(-1)`相當于`back()`。如果參數超過實際存在的網址范圍,該方法無效果;如果不指定參數,默認參數為`0`,相當于刷新當前頁面。
```javascript
history.back();
history.forward();
history.go(-2);
```
`history.go(0)`相當于刷新當前頁面。
```javascript
history.go(0); // 刷新當前頁面
```
注意,移動到以前訪問過的頁面時,頁面通常是從瀏覽器緩存之中加載,而不是重新要求服務器發送新的網頁。
### History.pushState(),
`History.pushState()`方法用于在歷史中添加一條記錄。
```javascript
window.history.pushState(state, title, url)
```
該方法接受三個參數,依次為:
- `state`:一個與添加的記錄相關聯的狀態對象,主要用于`popstate`事件。該事件觸發時,該對象會傳入回調函數。也就是說,瀏覽器會將這個對象序列化以后保留在本地,重新載入這個頁面的時候,可以拿到這個對象。如果不需要這個對象,此處可以填`null`。
- `title`:新頁面的標題。但是,現在所有瀏覽器都忽視這個參數,所以這里可以填空字符串。
- `url`:新的網址,必須與當前頁面處在同一個域。瀏覽器的地址欄將顯示這個網址。
假定當前網址是`example.com/1.html`,使用`pushState()`方法在瀏覽記錄(History 對象)中添加一個新記錄。
```javascript
var stateObj = { foo: 'bar' };
history.pushState(stateObj, 'page 2', '2.html');
```
添加新記錄后,瀏覽器地址欄立刻顯示`example.com/2.html`,但并不會跳轉到`2.html`,甚至也不會檢查`2.html`是否存在,它只是成為瀏覽歷史中的最新記錄。這時,在地址欄輸入一個新的地址(比如訪問`google.com`),然后點擊了倒退按鈕,頁面的 URL 將顯示`2.html`;你再點擊一次倒退按鈕,URL 將顯示`1.html`。
總之,`pushState()`方法不會觸發頁面刷新,只是導致 History 對象發生變化,地址欄會有反應。
使用該方法之后,就可以用`History.state`屬性讀出狀態對象。
```javascript
var stateObj = { foo: 'bar' };
history.pushState(stateObj, 'page 2', '2.html');
history.state // {foo: "bar"}
```
如果`pushState`的 URL 參數設置了一個新的錨點值(即`hash`),并不會觸發`hashchange`事件。反過來,如果 URL 的錨點值變了,則會在 History 對象創建一條瀏覽記錄。
如果`pushState()`方法設置了一個跨域網址,則會報錯。
```javascript
// 報錯
// 當前網址為 http://example.com
history.pushState(null, '', 'https://twitter.com/hello');
```
上面代碼中,`pushState`想要插入一個跨域的網址,導致報錯。這樣設計的目的是,防止惡意代碼讓用戶以為他們是在另一個網站上,因為這個方法不會導致頁面跳轉。
### History.replaceState()
`History.replaceState()`方法用來修改 History 對象的當前記錄,其他都與`pushState()`方法一模一樣。
假定當前網頁是`example.com/example.html`。
```javascript
history.pushState({page: 1}, 'title 1', '?page=1')
// URL 顯示為 http://example.com/example.html?page=1
history.pushState({page: 2}, 'title 2', '?page=2');
// URL 顯示為 http://example.com/example.html?page=2
history.replaceState({page: 3}, 'title 3', '?page=3');
// URL 顯示為 http://example.com/example.html?page=3
history.back()
// URL 顯示為 http://example.com/example.html?page=1
history.back()
// URL 顯示為 http://example.com/example.html
history.go(2)
// URL 顯示為 http://example.com/example.html?page=3
```
## popstate 事件
每當同一個文檔的瀏覽歷史(即`history`對象)出現變化時,就會觸發`popstate`事件。
注意,僅僅調用`pushState()`方法或`replaceState()`方法 ,并不會觸發該事件,只有用戶點擊瀏覽器倒退按鈕和前進按鈕,或者使用 JavaScript 調用`History.back()`、`History.forward()`、`History.go()`方法時才會觸發。另外,該事件只針對同一個文檔,如果瀏覽歷史的切換,導致加載不同的文檔,該事件也不會觸發。
使用的時候,可以為`popstate`事件指定回調函數。
```javascript
window.onpopstate = function (event) {
console.log('location: ' + document.location);
console.log('state: ' + JSON.stringify(event.state));
};
// 或者
window.addEventListener('popstate', function(event) {
console.log('location: ' + document.location);
console.log('state: ' + JSON.stringify(event.state));
});
```
回調函數的參數是一個`event`事件對象,它的`state`屬性指向`pushState`和`replaceState`方法為當前 URL 所提供的狀態對象(即這兩個方法的第一個參數)。上面代碼中的`event.state`,就是通過`pushState`和`replaceState`方法,為當前 URL 綁定的`state`對象。
這個`state`對象也可以直接通過`history`對象讀取。
```javascript
var currentState = history.state;
```
注意,頁面第一次加載的時候,瀏覽器不會觸發`popstate`事件。
- 前言
- 入門篇
- 導論
- 歷史
- 基本語法
- 數據類型
- 概述
- null,undefined 和布爾值
- 數值
- 字符串
- 對象
- 函數
- 數組
- 運算符
- 算術運算符
- 比較運算符
- 布爾運算符
- 二進制位運算符
- 其他運算符,運算順序
- 語法專題
- 數據類型的轉換
- 錯誤處理機制
- 編程風格
- console 對象與控制臺
- 標準庫
- Object 對象
- 屬性描述對象
- Array 對象
- 包裝對象
- Boolean 對象
- Number 對象
- String 對象
- Math 對象
- Date 對象
- RegExp 對象
- JSON 對象
- 面向對象編程
- 實例對象與 new 命令
- this 關鍵字
- 對象的繼承
- Object 對象的相關方法
- 嚴格模式
- 異步操作
- 概述
- 定時器
- Promise 對象
- DOM
- 概述
- Node 接口
- NodeList 接口,HTMLCollection 接口
- ParentNode 接口,ChildNode 接口
- Document 節點
- Element 節點
- 屬性的操作
- Text 節點和 DocumentFragment 節點
- CSS 操作
- Mutation Observer API
- 事件
- EventTarget 接口
- 事件模型
- Event 對象
- 鼠標事件
- 鍵盤事件
- 進度事件
- 表單事件
- 觸摸事件
- 拖拉事件
- 其他常見事件
- GlobalEventHandlers 接口
- 瀏覽器模型
- 瀏覽器模型概述
- window 對象
- Navigator 對象,Screen 對象
- Cookie
- XMLHttpRequest 對象
- 同源限制
- CORS 通信
- Storage 接口
- History 對象
- Location 對象,URL 對象,URLSearchParams 對象
- ArrayBuffer 對象,Blob 對象
- File 對象,FileList 對象,FileReader 對象
- 表單,FormData 對象
- IndexedDB API
- Web Worker
- 附錄:網頁元素接口
- a
- img
- form
- input
- button
- option
- video,audio