html5 storage api
localStorage
和 sessionStorage
是 html5
新增的用來儲存資料的物件,他們讓我們可以以鍵值對的形式儲存資訊。
為什麼要有 storage
?
我們已經有了 session
可以幫助我們儲存資訊,為何還需要 storage
呢?
- 各個瀏覽器的
cookie
長度大概只能在4kb
左右,而storage
大概能達到5M
,這意味著可以儲存更多的資訊 cookie
可以被後端更改,在每次進行網路請求的時候都會被髮送給伺服器,而storage
不會,這意味著這個儲存是完全受控於前端(JavaScript)的。
storage 型別
storage
一共有兩種
-
localStorage
這個儲存物件的儲存和
origin
有關,即只要是同域名同協議同埠,儲存是共享的。儘管關機了,或是關掉瀏覽器了,只要開啟同源網站,儲存的資料會依然存在,資料不會過期消失。 -
sessionStorage
這個儲存物件的儲存是暫時的,只保持在當前會話中,簡單來說就是和瀏覽器的一個
tab
有關,只要tab
關掉了再開啟資料就沒了,但是在當前介面重新整理的話,資料就還在(這個時候認為是一個tab
)。
兩個 storage
的 api
很相似,下面以 localStorage
為例
localStorage 演示
基礎 api
localStorage.setItem("name", "huro"); // 設定鍵值對
可以在 chrome
瀏覽器的控制檯進行觀察,這裡已經設定上去了。下面也可以做相應的測試。
localStorage.getItem("name"); // huro
localStorage.removeItem("name"); // 刪除某個鍵
localStorage.clear(); // 刪除所有鍵值對
localStorage.key(0); // 獲得索引為 0 的key
localStorage.length; // 獲得 `localStroage` 的鍵的個數
以上是 storage
的 api
唯一需要注意的是 key(index)
這個 api
和 key
被設定的先後是沒有關係的。
類物件操作
也可以用類物件的方法操作
localStorage.name = "huro";
console.log(localStorage.name); // huro
delete localStorage.name; // 刪除鍵
但是上面的做法不推薦,如果用的是某些特殊的 key
例如 length
就會報錯,因為原先 localStorage.length
表示獲得鍵值對長度,理應是不能修改的。
localStorage["length"] = 4; // 修改無效
因此不推薦用這個做法修改 storage
遍歷鍵值
由於 storage
並沒有 Symbol.iterator
屬性,這意味著 storage
不能用 for of
迴圈遍歷。以下有三種遍歷方式。
假設我們只有一個鍵值對 name: huro
for in
迴圈
for (let key in localStorage) {
console.log(key);
}
上述的寫法是錯誤的,因為 for in
迴圈會遍歷原型鏈上的屬性和方法,因此需要稍作改善。
for (let key in localStorage) {
if (!localStorage.hasOwnProperty(key)) {
continue;
}
console.log(key);
}
這個時候就能正確的只列印出鍵 name
- 簡單
for
迴圈
for(let i = 0; i < localStorage.length; i+= 1) {
let key = localStorage.key(i);
console.log(key);
}
這個時候能正確的只列印出鍵 name
Object.keys()
這個方法會獲得某個物件自身的 key
,而不會管原型鏈上的
const keys = Object.keys(localStorage);
for(let key of keys) {
alert(key);
}
而且獲得的 key
是陣列,具有 iterator
因此可以用 for of
遍歷
這個時候能正確的只列印出鍵 name
只能是 string
storage
被設計出來比較不足的地方是,鍵和值都只能是 string
型別的,如果不是的話,會自動轉換成 string
。
由於是隱式轉換,初學者往往不知道,這意味著可能帶來一些 bug
localStorage.user = { name: "huro" };
console.log(localStorage.user); // [object Object]
上述程式碼在儲存 user
的時候,被自動呼叫 toString
方法,轉化為了 [object Object]
storage
事件
storage
事件返回一個物件,裡面包含幾個引數
key
改變的鍵oldValue
=>舊值 || null
newValue
=>新值 || null
url
觸發這個事件的url
地址storageArea
要麼是localStorage
要麼是sessionStorage
取決與是更改哪個storage
的
// 1.html
window.addEventListener("storage", (state) => {
console.log(state.key, state.value, state.url); // name huro ./2.html(實際 url 是絕對路徑)
})
// 2.html
localStorage.setItem("name", "huro");
還記得我們之前說過, localStorage
只要是同源都可以分享嗎,這意味如果我們開啟了兩個視窗,只要他們是同源的,我們可以用上述的監聽事件,監聽另一個埠修改 storage
,也就是可以實現不同的視窗之間的資料共享。
注意: 經測試,chrome
edge
等現代瀏覽器不會觸發自身檔案或同檔案的 storage
事件,即必須是兩個不同的 html
才會互相觸發。
例如 test1.html
和 test2.html
都設定了 storage
監聽事件,且同源。
則 test1.html
的 storage
的 api
事件會觸發 test2.html
的,但是不能觸發本身的 storage
監聽事件。
另外這裡的 api
事件也有限制,經過筆者測試,似乎只有
setItem
getItem
removeItem
有效果,而 clear
事件是沒有效果的。
上面全程用 localStorage
演示,
sessionStorage
也是類似的,讀者有興趣可以自行碼一下程式碼。
總結
storage
是很好的一個 html5
特性,讓我們方便快捷的儲存資料,美中不足的是隻能儲存字元型資料,不過也很容易解決這個問題。同時利用監聽事件,也可以實現不同視窗之間的廣播機制。是非常實用的一個特性。