使用 Web Storage API
Web Storage API 提供了浏览器安全存储键/值对的机制。
本文将介绍如何使用这项技术。
基本概念
Storage 对象是简单的键/值存储,类似于对象,但它们在页面加载之间保持不变。键和值始终是字符串(请注意,与对象一样,整数键会自动转换为字符串)。你可以像访问对象一样访问这些值,或者使用 Storage.getItem() 和 Storage.setItem() 方法。这三行代码都设置了(相同的)colorSetting 条目。
localStorage.colorSetting = "#a4509b";
localStorage["colorSetting"] = "#a4509b";
localStorage.setItem("colorSetting", "#a4509b");
注意: 建议使用 Web Storage API(setItem、getItem、removeItem、key、length)来避免使用普通对象作为键/值存储所带来的 陷阱。
Web Storage 中的两种机制如下:
sessionStorage为每个给定的源维护一个单独的存储区域,该区域在页面会话期间(只要浏览器打开,包括页面重新加载和恢复)可用。localStorage执行相同的功能,但在浏览器关闭和重新打开后仍会持久化。
这些机制可以通过 Window.sessionStorage 和 Window.localStorage 属性访问(更准确地说,在支持的浏览器中,Window 对象实现了 WindowLocalStorage 和 WindowSessionStorage 对象,而 localStorage 和 sessionStorage 属性是这些对象的成员)——调用其中一个将创建一个 Storage 对象实例,通过该实例可以设置、检索和删除数据项。对于每个源的 sessionStorage 和 localStorage 会使用不同的 Storage 对象——它们的功能和控制是分开的。
因此,例如,最初在文档上调用 localStorage 将返回一个 Storage 对象;在文档上调用 sessionStorage 将返回一个不同的 Storage 对象。两者都可以用相同的方式进行操作,但彼此独立。
检测 localStorage 的支持情况
要能够使用 localStorage,我们应该首先验证它是否在当前浏览会话中受支持且可用。
测试可用性
支持 localStorage 的浏览器在 window 对象上有一个名为 localStorage 的属性。但是,仅仅测试属性是否存在,就像在正常的特性检测中一样,可能不足够。各种浏览器提供了禁用存储 API 的设置,而不会隐藏全局对象。因此,浏览器可能支持 localStorage,但不向页面上的脚本提供它。
例如,对于在浏览器隐私浏览模式下查看的文档,某些浏览器可能会提供一个配额为零的空 localStorage 对象,实际上使其无法使用。反之,我们也可能会收到一个合法的 QuotaExceededError,这意味着我们已经用完了所有可用的存储空间,但存储确实可用。我们的特性检测应该考虑到这些情况。
这是一个检测 localStorage 是否被支持且可用的函数:
function storageAvailable(type) {
let storage;
try {
storage = window[type];
const x = "__storage_test__";
storage.setItem(x, x);
storage.removeItem(x);
return true;
} catch (e) {
return (
e instanceof DOMException &&
e.name === "QuotaExceededError" &&
// acknowledge QuotaExceededError only if there's something already stored
storage &&
storage.length !== 0
);
}
}
以下是如何使用它:
if (storageAvailable("localStorage")) {
// Yippee! We can use localStorage awesomeness
} else {
// Too bad, no localStorage for us
}
你可以通过调用 storageAvailable("sessionStorage") 来改用 sessionStorage 进行测试。
示例
为了说明一些典型的 Web Storage 用法,我们创建了一个名为“Web Storage Demo”的示例。该 主页 提供了用于自定义颜色、字体和装饰图像的控件。

当您选择不同的选项时,页面会立即更新;此外,您的选择会存储在 localStorage 中,因此当您离开页面并稍后重新加载它时,您的选择会被记住。
我们还提供了一个 事件输出页面 — 如果您在另一个标签页中加载此页面,然后更改主页中的选择,您将看到更新的存储信息作为 StorageEvent 触发的输出。

注意: 除了通过上面的链接实时查看示例页面外,您还可以 查看源代码。
测试您的存储是否已填充
首先,在 main.js 中,我们测试存储对象是否已填充(即,页面之前已被访问)。
if (!localStorage.getItem("bgcolor")) {
populateStorage();
} else {
setStyles();
}
Storage.getItem() 方法用于从存储中获取数据项;在这种情况下,我们正在测试 bgcolor 项是否存在;如果不存在,我们运行 populateStorage() 将现有的自定义值添加到存储中。如果已经存在值,我们运行 setStyles() 以存储的值更新页面样式。
注意: 您也可以使用 Storage.length 来测试存储对象是否为空。
从存储中获取值
如上所述,可以使用 Storage.getItem() 从存储中检索值。它以数据项的键作为参数,并返回数据值。
例如
function setStyles() {
const currentColor = localStorage.getItem("bgcolor");
const currentFont = localStorage.getItem("font");
const currentImage = localStorage.getItem("image");
document.getElementById("bgcolor").value = currentColor;
document.getElementById("font").value = currentFont;
document.getElementById("image").value = currentImage;
htmlElem.style.backgroundColor = `#${currentColor}`;
pElem.style.fontFamily = currentFont;
imgElem.setAttribute("src", currentImage);
}
这里,前三行从本地存储中获取值。接下来,我们将表单元素中显示的值设置为这些值,以便在重新加载页面时保持同步。最后,我们更新页面上的样式/装饰图像,以便在重新加载时再次显示您的自定义选项。
将值设置到存储中
Storage.setItem() 用于创建新数据项,以及(如果数据项已存在)更新现有值。它接受两个参数——要创建/修改的数据项的键,以及要存储的值。
function populateStorage() {
localStorage.setItem("bgcolor", document.getElementById("bgcolor").value);
localStorage.setItem("font", document.getElementById("font").value);
localStorage.setItem("image", document.getElementById("image").value);
setStyles();
}
populateStorage() 函数在本地存储中设置三个项——背景颜色、字体和图像路径。然后它运行 setStyles() 函数来更新页面样式等。
我们还在每个表单元素上包含了一个 onchange 处理程序,以便在更改表单值时更新数据和样式。
bgcolorForm.onchange = populateStorage;
fontForm.onchange = populateStorage;
imageForm.onchange = populateStorage;
Storage 只支持存储和检索字符串。如果你想保存其他数据类型,你必须将它们转换为字符串。对于普通对象和数组,可以使用 JSON.stringify()。
const person = { name: "Alex" };
localStorage.setItem("user", person);
console.log(localStorage.getItem("user")); // "[object Object]"; not useful!
localStorage.setItem("user", JSON.stringify(person));
console.log(JSON.parse(localStorage.getItem("user"))); // { name: "Alex" }
然而,没有通用的方法可以存储任意数据类型。此外,检索到的对象是原始对象的深拷贝,对它的修改不会影响原始对象。
使用 StorageEvent 响应存储更改
当共享相同存储空间的另一个文档的 Storage 对象发生更改时,将触发 storage 事件。这在进行更改的同一页面上不起作用——它实际上是一种让使用该存储的其他页面同步所做更改的方式。其他来源的页面无法访问相同的存储对象。
对于 localStorage,存储空间由同一来源的所有选项卡共享。对于 sessionStorage,存储空间仅在选项卡内共享, among all iframes from the same origin(在同一来源的所有 iframe 之间共享)。
在事件页面(参见 events.js)上,唯一的 JavaScript 如下:
window.addEventListener("storage", (e) => {
document.querySelector(".my-key").textContent = e.key;
document.querySelector(".my-old").textContent = e.oldValue;
document.querySelector(".my-new").textContent = e.newValue;
document.querySelector(".my-url").textContent = e.url;
document.querySelector(".my-storage").textContent = JSON.stringify(
e.storageArea,
);
});
这里我们向 window 对象添加了一个事件监听器,当与当前来源相关的 Storage 对象发生更改时触发。如上所示,与此事件关联的事件对象具有许多包含有用信息的属性——更改的数据的键,更改前的值,更改后的新值,更改存储的文档的 URL,以及存储对象本身(我们已将其字符串化,以便您可以看到其内容)。
删除数据记录
Web Storage 还提供了一些简单的删除数据的方法。我们在演示中没有使用它们,但将它们添加到您的项目中非常简单。
Storage.removeItem()接受一个参数——您要删除的数据项的键——并将其从该来源的存储对象中删除。Storage.clear()不接受任何参数,并清空该来源的整个存储对象。
规范
| 规范 |
|---|
| HTML # dom-localstorage-dev |
| HTML # dom-sessionstorage-dev |
浏览器兼容性
api.Window.localStorage
加载中…
api.Window.sessionStorage
加载中…