Objekty webového úložiště localStorage
a sessionStorage
umožňují uložit páry klíč/hodnota v prohlížeči.
Zajímavé na nich je, že data přežijí obnovení stránky (pro sessionStorage
) a dokonce i úplný restart prohlížeče (pro localStorage
). To uvidíme velmi brzy.
Už máme sušenky. Proč další objekty?
- Na rozdíl od souborů cookie se objekty webového úložiště neodesílají na server s každým požadavkem. Díky tomu můžeme uložit mnohem více. Většina moderních prohlížečů umožňuje alespoň 5 megabajtů dat (nebo více) a má nastavení pro jeho konfiguraci.
- Na rozdíl od souborů cookie také server nemůže manipulovat s objekty úložiště prostřednictvím záhlaví HTTP. Vše se děje v JavaScriptu.
- Úložiště je vázáno na zdroj (triplet doména/protokol/port). To znamená, že různé protokoly nebo subdomény vyvozují různé objekty úložiště, nemohou navzájem přistupovat k datům.
Oba objekty úložiště poskytují stejné metody a vlastnosti:
setItem(key, value)
– uložit pár klíč/hodnota.getItem(key)
– získat hodnotu pomocí klíče.removeItem(key)
– odeberte klíč s jeho hodnotou.clear()
– smazat vše.key(index)
– získat klíč na dané pozici.length
– počet uložených položek.
Jak můžete vidět, je to jako Map
kolekce (setItem/getItem/removeItem
), ale také umožňuje přístup pomocí indexu s key(index)
.
Podívejme se, jak to funguje.
ukázka místního úložiště
Hlavní rysy localStorage
jsou:
- Sdíleno mezi všemi kartami a okny ze stejného zdroje.
- Platnost dat nevyprší. Zůstane po restartu prohlížeče a dokonce i restartu OS.
Pokud například spustíte tento kód…
localStorage.setItem('test', 1);
…A zavřete/otevřete prohlížeč nebo prostě otevřete stejnou stránku v jiném okně, pak to můžete získat takto:
alert( localStorage.getItem('test') ); // 1
Musíme být pouze na stejném původu (doména/port/protokol), cesta url se může lišit.
localStorage
je sdílen mezi všemi okny se stejným původem, takže pokud nastavíme data v jednom okně, změna se projeví v jiném.
Objektový přístup
Můžeme také použít jednoduchý objektový způsob získávání/nastavení klíčů, jako je tento:
// set key
localStorage.test = 2;
// get key
alert( localStorage.test ); // 2
// remove key
delete localStorage.test;
To je z historických důvodů povoleno a většinou to funguje, ale obecně se to nedoporučuje, protože:
-
Pokud je klíč vygenerován uživatelem, může to být cokoliv, například
length
nebotoString
nebo jinou vestavěnou metodoulocalStorage
. V tom případěgetItem/setItem
funguje dobře, zatímco objektový přístup selže:let key = 'length'; localStorage[key] = 5; // Error, can't assign length
-
Je tam
storage
událost se spustí, když upravíme data. K této události nedochází u objektového přístupu. To uvidíme později v této kapitole.
Procházení kláves
Jak jsme viděli, metody poskytují funkci „získat/nastavit/odebrat pomocí klíče“. Jak ale získat všechny uložené hodnoty nebo klíče?
Objekty úložiště bohužel nelze iterovat.
Jedním ze způsobů je smyčka přes ně jako přes pole:
for(let i=0; i<localStorage.length; i++) {
let key = localStorage.key(i);
alert(`${key}: ${localStorage.getItem(key)}`);
}
Dalším způsobem je použití for key in localStorage
smyčky, stejně jako to děláme s běžnými objekty.
Iteruje přes klíče, ale také vydává několik vestavěných polí, která nepotřebujeme:
// bad try
for(let key in localStorage) {
alert(key); // shows getItem, setItem and other built-in stuff
}
…Potřebujeme tedy buď filtrovat pole z prototypu pomocí hasOwnProperty
zkontrolujte:
for(let key in localStorage) {
if (!localStorage.hasOwnProperty(key)) {
continue; // skip keys like "setItem", "getItem" etc
}
alert(`${key}: ${localStorage.getItem(key)}`);
}
…Nebo stačí získat „vlastní“ klíče s Object.keys
a v případě potřeby přes ně smyčku:
let keys = Object.keys(localStorage);
for(let key of keys) {
alert(`${key}: ${localStorage.getItem(key)}`);
}
To druhé funguje, protože Object.keys
vrací pouze klíče, které patří k objektu, ignoruje prototyp.
Pouze řetězce
Pamatujte, že klíč i hodnota musí být řetězce.
Pokud by šlo o jakýkoli jiný typ, například číslo nebo objekt, převede se na řetězec automaticky:
localStorage.user = {name: "John"};
alert(localStorage.user); // [object Object]
Můžeme použít JSON
pro ukládání objektů:
localStorage.user = JSON.stringify({name: "John"});
// sometime later
let user = JSON.parse( localStorage.user );
alert( user.name ); // John
Také je možné stringovat celý objekt úložiště, např. pro účely ladění:
// added formatting options to JSON.stringify to make the object look nicer
alert( JSON.stringify(localStorage, null, 2) );
sessionStorage
sessionStorage
objekt se používá mnohem méně často než localStorage
.
Vlastnosti a metody jsou stejné, ale jsou mnohem omezenější:
sessionStorage
existuje pouze na aktuální kartě prohlížeče.- Jiná karta se stejnou stránkou bude mít jiné úložiště.
- Je však sdílen mezi prvky iframe na stejné kartě (za předpokladu, že pocházejí ze stejného původu).
- Data vydrží obnovení stránky, ale nezavření/otevření karty.
Podívejme se na to v praxi.
Spusťte tento kód…
sessionStorage.setItem('test', 1);
…Pak obnovte stránku. Nyní můžete stále získat data:
alert( sessionStorage.getItem('test') ); // after refresh: 1
…Pokud ale stejnou stránku otevřete na jiné kartě a zkusíte to tam znovu, výše uvedený kód vrátí null
, což znamená „nic nebylo nalezeno“.
To je přesně proto, že sessionStorage
je vázán nejen na původ, ale také na kartu prohlížeče. Z tohoto důvodu sessionStorage
se používá střídmě.
Událost úložiště
Když se data aktualizují v localStorage
nebo sessionStorage
, spouštěče událostí úložiště, s vlastnostmi:
key
– klíč, který byl změněn (null
pokud.clear()
se nazývá).oldValue
– stará hodnota (null
pokud je klíč nově přidán).newValue
– nová hodnota (null
pokud je klíč odstraněn).url
– adresa URL dokumentu, kde došlo k aktualizaci.storageArea
– buďlocalStorage
nebosessionStorage
objekt, kde k aktualizaci došlo.
Důležité je:událost se spustí na všech window
objekty, kde je úložiště přístupné, kromě toho, který to způsobil.
Pojďme to upřesnit.
Představte si, že máte dvě okna se stejným webem v každém. Takže localStorage
je sdílena mezi nimi.
Možná budete chtít otevřít tuto stránku ve dvou oknech prohlížeče a otestovat níže uvedený kód.
Pokud obě okna naslouchají window.onstorage
, pak každý z nich bude reagovat na aktualizace, ke kterým došlo v druhém.
// triggers on updates made to the same storage from other documents
window.onstorage = event => { // can also use window.addEventListener('storage', event => {
if (event.key != 'now') return;
alert(event.key + ':' + event.newValue + " at " + event.url);
};
localStorage.setItem('now', Date.now());
Upozorňujeme, že událost také obsahuje:event.url
– adresa URL dokumentu, kde byla data aktualizována.
Také event.storageArea
obsahuje objekt úložiště – událost je stejná pro oba sessionStorage
a localStorage
, takže event.storageArea
odkazuje na ten, který byl upraven. Můžeme v něm dokonce chtít něco nastavit, abychom „reagovali“ na změnu.
To umožňuje různým oknům ze stejného zdroje vyměňovat si zprávy.
Moderní prohlížeče také podporují Broadcast channel API, speciální API pro komunikaci mezi okny stejného původu, je plnohodnotnější, ale méně podporované. Existují knihovny, které toto API polyfillují na základě localStorage
, díky kterým je dostupná všude.
Shrnutí
Objekty webového úložiště localStorage
a sessionStorage
umožňují uložit klíč/hodnotu v prohlížeči.
- Oba
key
avalue
musí být řetězce. - Limit je 5 MB+, záleží na prohlížeči.
- Jejich platnost nevyprší.
- Data jsou vázána na zdroj (doména/port/protokol).
localStorage | sessionStorage |
---|---|
Sdíleno mezi všemi kartami a okny se stejným původem | Viditelné na kartě prohlížeče, včetně prvků iframe ze stejného původu |
Přežije restart prohlížeče | Přetrvává obnovení stránky (ale ne zavření karty) |
API:
setItem(key, value)
– uložit pár klíč/hodnota.getItem(key)
– získat hodnotu pomocí klíče.removeItem(key)
– odeberte klíč s jeho hodnotou.clear()
– smazat vše.key(index)
– získat číslo klíčeindex
.length
– počet uložených položek.- Použijte
Object.keys
získat všechny klíče. - Ke klíčům přistupujeme jako k vlastnostem objektu, v tomto případě
storage
událost není spuštěna.
Událost úložiště:
- Spouští na
setItem
,removeItem
,clear
hovory. - Obsahuje všechna data o operaci (
key/oldValue/newValue
), dokumenturl
a objekt úložištěstorageArea
. - Spouštěče na všech
window
objekty, které mají přístup k úložišti kromě toho, který jej vygeneroval (na kartě prosessionStorage
, globálně prolocalStorage
).