W3Cschool
恭喜您成為首批注冊用戶
獲得88經驗值獎勵
Web 存儲對象 ?localStorage
? 和 ?sessionStorage
? 允許我們在瀏覽器上保存鍵/值對。
它們有趣的是,在頁面刷新后(對于 sessionStorage
)甚至瀏覽器完全重啟(對于 localStorage
)后,數(shù)據(jù)仍然保留在瀏覽器中。我們很快就會看到。
我們已經有了 cookie。為什么還要其他存儲對象呢?
兩個存儲對象都提供相同的方法和屬性:
setItem(key, value)
? —— 存儲鍵/值對。getItem(key)
? —— 按照鍵獲取值。removeItem(key)
? —— 刪除鍵及其對應的值。clear()
? —— 刪除所有數(shù)據(jù)。key(index)
? —— 獲取該索引下的鍵名。length
? —— 存儲的內容的長度。正如你所看到的,它就像一個 Map
集合(setItem/getItem/removeItem
),但也允許通過 key(index)
來按索引訪問。
讓我們看看它是如何工作的吧。
localStorage
最主要的特點是:
例如,如果你運行此代碼……
localStorage.setItem('test', 1);
……然后關閉/重新打開瀏覽器,或者只是在不同的窗口打開同一頁面,然后你可以這樣獲取它:
alert( localStorage.getItem('test') ); // 1
我們只需要在同一個源(域/端口/協(xié)議),URL 路徑可以不同。
在所有同源的窗口之間,localStorage
數(shù)據(jù)可以共享。因此,如果我們在一個窗口中設置了數(shù)據(jù),則在另一個窗口中也可以看到數(shù)據(jù)變化。
我們還可以像使用一個普通對象那樣,讀取/設置鍵,像這樣:
// 設置 key
localStorage.test = 2;
// 獲取 key
alert( localStorage.test ); // 2
// 刪除 key
delete localStorage.test;
這是歷史原因造成的,并且大多數(shù)情況下都可行,但通常不建議這樣做,因為:
length
或 toString
,也可以是 localStorage
的另一種內建方法。在這種情況下,getItem/setItem
可以正常工作,而類對象訪問的方式則會失?。?/li>
let key = 'length';
localStorage[key] = 5; // Error,無法對 length 進行賦值
storage
? 事件,在我們更改數(shù)據(jù)時會觸發(fā)。但以類對象方式訪問時,不會觸發(fā)該事件。我們將在本章的后面看到。正如我們所看到的,這些方法提供了“按照鍵獲取/設置/刪除”的功能。但我們如何獲取所有保存的值或鍵呢?
不幸的是,存儲對象是不可迭代的。
一種方法是像遍歷數(shù)組那樣遍歷它們:
for(let i = 0; i < localStorage.length; i++) {
let key = localStorage.key(i);
alert(`${key}: ${localStorage.getItem(key)}`);
}
另一個方式是使用 for key in localStorage
循環(huán),就像處理常規(guī)對象一樣。
它會遍歷所有的鍵,但也會輸出一些我們不需要的內建字段。
// 不好的嘗試
for(let key in localStorage) {
alert(key); // 顯示 getItem,setItem 和其他內建的東西
}
……因此,我們需要使用 hasOwnProperty
檢查來過濾掉原型中的字段:
for(let key in localStorage) {
if (!localStorage.hasOwnProperty(key)) {
continue; // 跳過像 "setItem","getItem" 等這樣的鍵
}
alert(`${key}: ${localStorage.getItem(key)}`);
}
……或者,使用 Object.keys
獲取只屬于“自己”的鍵,然后如果需要,可以遍歷它們:
let keys = Object.keys(localStorage);
for(let key of keys) {
alert(`${key}: ${localStorage.getItem(key)}`);
}
后者有效,因為 Object.keys
只返回屬于對象的鍵,會忽略原型上的。
請注意,鍵和值都必須是字符串。
如果是任何其他類型,例數(shù)字或對象,它會被自動轉換為字符串。
localStorage.user = {name: "John"};
alert(localStorage.user); // [object Object]
我們可以使用 JSON
來存儲對象:
localStorage.user = JSON.stringify({name: "John"});
// sometime later
let user = JSON.parse( localStorage.user );
alert( user.name ); // John
也可以對整個存儲對象進行字符串化處理,例如出于調試目的:
// 為 JSON.stringify 增加了格式設置選項,以使對象看起來更美觀
alert( JSON.stringify(localStorage, null, 2) );
sessionStorage
對象的使用頻率比 localStorage
對象低得多。
屬性和方法是相同的,但是它有更多的限制:
sessionStorage
? 的數(shù)據(jù)只存在于當前瀏覽器標簽頁。讓我們看看它的運行效果。
運行此代碼……
sessionStorage.setItem('test', 1);
……然后刷新頁面。這時你仍然可以獲取到數(shù)據(jù):
alert( sessionStorage.getItem('test') ); // after refresh: 1
……但是,如果你在另一個新的標簽頁中打開此頁面,然后在新頁面中再次運行上面這行代碼,則會得到 null
,表示“未找到數(shù)據(jù)”。
這是因為 sessionStorage
不僅綁定到源,還綁定在同一瀏覽器標簽頁。因此,sessionStorage
很少被使用。
當 localStorage
或 sessionStorage
中的數(shù)據(jù)更新后,storage 事件就會觸發(fā),它具有以下屬性:
key
? —— 發(fā)生更改的數(shù)據(jù)的 ?key
?(如果調用的是 ?.clear()
? 方法,則為 ?null
?)。oldValue
? —— 舊值(如果是新增數(shù)據(jù),則為 ?null
?)。newValue
? —— 新值(如果是刪除數(shù)據(jù),則為 ?null
?)。url
? —— 發(fā)生數(shù)據(jù)更新的文檔的 url。storageArea
? —— 發(fā)生數(shù)據(jù)更新的 ?localStorage
? 或 ?sessionStorage
? 對象。重要的是:該事件會在所有可訪問到存儲對象的 window
對象上觸發(fā),導致當前數(shù)據(jù)改變的 window
對象除外。
我們來詳細解釋一下。
想象一下,你有兩個窗口,它們具有相同的頁面。所以 localStorage
在它們之間是共享的。
你可以想在瀏覽器的兩個窗口中打開此頁面來測試下面的代碼。
如果兩個窗口都在監(jiān)聽 window.onstorage
事件,那么每個窗口都會對另一個窗口中發(fā)生的更新作出反應。
// 在其他文檔對同一存儲進行更新時觸發(fā)
window.onstorage = event => { // 也可以使用 window.addEventListener('storage', event => {
if (event.key != 'now') return;
alert(event.key + ':' + event.newValue + " at " + event.url);
};
localStorage.setItem('now', Date.now());
請注意,該事件還包含:event.url
—— 發(fā)生數(shù)據(jù)更新的文檔的 url。
并且,event.storageArea
包含存儲對象 —— sessionStorage
和 localStorage
具有相同的事件,所以 event.storageArea
引用了被修改的對象。我們可能會想設置一些東西,以“響應”更改。
這允許同源的不同窗口交換消息。
現(xiàn)代瀏覽器還支持 Broadcast channel API,這是用于同源窗口之間通信的特殊 API,它的功能更全,但被支持的情況不好。有一些庫基于 localStorage
來 polyfill 該 API,使其可以用在任何地方。
Web 存儲對象 ?localStorage
? 和 ?sessionStorage
? 允許我們在瀏覽器中保存鍵/值對。
key
? 和 ?value
? 都必須為字符串。localStorage
|
sessionStorage
|
---|---|
在同源的所有標簽頁和窗口之間共享數(shù)據(jù) | 在當前瀏覽器標簽頁中可見,包括同源的 iframe |
瀏覽器重啟后數(shù)據(jù)仍然保留 | 頁面刷新后數(shù)據(jù)仍然保留(但標簽頁關閉后數(shù)據(jù)則不再保留) |
API:
setItem(key, value)
? —— 存儲鍵/值對。getItem(key)
? —— 按照鍵獲取值。removeItem(key)
? —— 刪除鍵及其對應的值。clear()
? —— 刪除所有數(shù)據(jù)。key(index)
? —— 獲取該索引下的鍵名。length
? —— 存儲的內容的長度。Object.keys
? 來獲取所有的鍵。storage
? 事件。Storage 事件:
setItem
?,?removeItem
?,?clear
? 方法后觸發(fā)。key/oldValue/newValue
?),文檔 ?url
? 和存儲對象 ?storageArea
?。window
? 對象上觸發(fā),導致當前數(shù)據(jù)改變的 ?window
? 對象除外(對于 ?sessionStorage
? 是在當前標簽頁下,對于 ?localStorage
? 是在全局,即所有同源的窗口)。創(chuàng)建一個 textarea
字段,每當其值發(fā)生變化時,可以將其“自動保存”。
因此,如果用戶不小心關閉了頁面,然后重新打開,他會發(fā)現(xiàn)之前未完成的輸入仍然保留在那里。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: