sessionStorage 與 localStorage 差不多可以算作一對兄弟,它倆的暴露的 API 方法一模一樣。
但兩者也有不同點:
1、sessionStorage 存入的數據在頁面關閉後,會自動清除。
2、相同 URL 的每個 tab 頁籤的 sessionStorage 會被隔離,互不影響。也就是説相同的鏈接,在 A 標籤頁打開和在 B 標籤打開,A 寫入的 sessionStorage 數據,B 是無法讀取的!!這裏與 會話 Cookie 完全不一樣。
3、在頁面中使用 <a target="_blank" rel="opener"> 和 window.open 打開新的標籤頁,sessionStorage 數據會複製,但之後的修改相互隔離。
4、sessionStorage 存入的數據會在瀏覽器打開期間一直保留,刷新頁面或使用 ctrl + shift + t 恢復頁面時,數據不會丟失。
API
sessionStorage 暴露的接口與 localStorage 一致:
// 只讀屬性,返回會話存儲項的數目
sessionStorage.length
// 獲取會話存儲的第 n 個鍵名
sessionStorage.key(n)
// 獲取會話存儲的值
sessionStorage.getItem(key)
// 寫入會話存儲
sessionStorage.setItem(key, value)
// 刪除會話存儲
sessionStorage.removeItem(key)
// 清空所有會話存儲
sessionStorage.clear()
API 使用示例:
(() => {
// 寫入數據
sessionStorage.setItem('type', '公眾號');
sessionStorage.setItem('name', '前端路引');
// 獲取會話存儲長度
console.log(sessionStorage.length);
// 循環打印會話存儲
for (let i = 0; i < sessionStorage.length; i++) {
const key = sessionStorage.key(i);
const value = sessionStorage.getItem(key);
console.log(`${key}: ${value}`);
}
// 移除單個會話存儲
sessionStorage.removeItem('name');
// 移除所有會話存儲
sessionStorage.clear();
})()
無法監聽存儲數據變化
不像 localStorage,sessionStorage 沒有暴露 onchange 事件,所以無法監聽到數據變化,就算模擬自定義事件,也只能在當前頁面中獲得事件,無法跨頁面通信。以下代碼只能在本頁面中監聽 sessionStorage 數據改變:
(() => {
// 移除所有會話存儲
sessionStorage.clear();
// 監聽 storage 事件
window.addEventListener('storage', e => {
console.log(e);
})
// 自定義寫入函數,封裝事件派發
function setItem (key, value) {
// 模擬 storage 事件
const ev = new StorageEvent('storage', {
key,
newValue: value,
oldValue: sessionStorage.getItem(key),
url: location.href,
});
window.dispatchEvent(ev);
sessionStorage.setItem(key, value);
}
setItem('type', '公眾號');
setItem('name', '前端路引');
})()
測試結果:

新開頁面複製 sessionStorage
在 a 標籤中添加 rel="opener" 可令新開的頁面獲得父頁面中的 sessionStorage 數據(複製方式)。
window.open 方法打開的頁面也是一樣的道理。
注意:此時獲得數據僅僅是副本,不共享,所以在新頁面或舊頁面中修改數據時,兩者互不影響。
a 標籤默認是 noopener,如果不顯示設置 rel="opener",無法獲得數據副本!!
測試代碼:
<a
href="./example-84-3.html"
target="_blank"
>a 標籤打開本頁面</a><br><br>
<a
href="./example-84-3.html"
target="_blank"
rel="opener"
>a 標籤 opener 打開本頁面</a><br><br>
<a
href="./example-84-3.html"
target="_blank"
rel="noopener"
>a 標籤 noopener 打開本頁面</a><br><br>
<button
onclick="window.open('./example-84-3.html')"
>window.open 打開本頁面</button><br><br>
<button
onclick="window.open('./example-84-3.html', '_blank', 'noopener')"
>window.open noopener 打開本頁面</button><br><br>
<button id="set">寫入新的 sessionStorage</button><br><br>
<button id="get">獲取 sessionStorage</button><br><br>
<div id="output"></div>
<script>
(() => {
const output = document.querySelector('#output');
document.querySelector('#set').addEventListener('click', e => {
sessionStorage.setItem('now', Date.now());
})
document.querySelector('#get').addEventListener('click', e => {
const now = sessionStorage.getItem('now');
output.innerText = now ?? '無';
})
})()
</script>
測試結果:

大小限制
與 localStorage 一樣限制 5MB 大小(所有鍵值加在一起的長度),溢出後寫入報錯,此處推薦閲讀前一篇文章:{%post_link 'wechat-web-front-end-83'%}
測試代碼:
(() => {
// 移除所有會話存儲
sessionStorage.clear();
const key = 'name';
const max = 5 * 1024 * 1024;
// 測試極限值
// const value = 'a'.repeat(max - key.length);
// 測試中文
// const value = '中'.repeat(max - key.length);
// 測試溢出
const value = 'a'.repeat(max - key.length + 1);
sessionStorage.setItem(key, value);
// 測試多個項溢出情況
// sessionStorage.setItem('key', '1');
// 測試與 localStorage 是否共用存儲空間
// localStorage.setItem('key', '1');
})()
溢出結果:

結論:setItem 多個子項時,公用 5MB 存儲空間(中英文計算方式一致),溢出時寫入報錯,並且與 localStorage 不共用存儲空間!使用 rel="opener" 打開鏈接時,會獲得父頁面的副本數據,所以新開的頁面僅能寫入 5MB - 副本數據 等到的剩下空間。
可使用以下代碼判斷是否擁有副本數據:
if (window.opener) {
// opener 存在表示擁有副本
// 極限情況再寫入新的數據報錯
sessionStorage.setItem('now', Date.now());
}
刷新與恢復頁面
頁面刷新時和關閉頁面後再使用 ctrl+shift+t 恢復頁面,sessionStorage 數據不會丟失。
測試代碼:
<button id="set">寫入新的 sessionStorage</button><br><br>
<button id="get">獲取 sessionStorage</button><br><br>
<div id="output"></div>
<script>
(() => {
const output = document.querySelector('#output');
document.querySelector('#set').addEventListener('click', e => {
sessionStorage.setItem('now', Date.now());
})
document.querySelector('#get').addEventListener('click', e => {
const now = sessionStorage.getItem('now');
output.innerText = now ?? '無';
})
})()
</script>
效果:

寫在最後
sessionStorage 僅支持字符串存儲,所以 JS 中用的 JSON 數據需要格式化為字符串存儲~~
sessionStorage 一般多用於臨時數據存儲,比如一些表單填寫的臨時數據,單頁應用頁面間的數據傳遞等。
其生命週期有點短暫,瀏覽器或標籤頁關閉就會消失,就像浮游一樣,朝生暮死...