Web Storage API 提供了存储机制,通过该机制,浏览器可以安全地存储键值对,比使用 cookie 更加直观。这篇文章一步一步讲解如何使用这项简单的技术。
基本概念
Web Storage 包含如下两种机制:
sessionStorage
为每一个给定的源(given origin)维持一个独立的存储区域,该存储区域在页面会话期间可用(即只要浏览器处于打开状态,包括页面重新加载和恢复)。localStorage
同样的功能,但是在浏览器关闭,然后重新打开后数据仍然存在。
这两种机制是通过 Window.sessionStorage
和 Window.localStorage
属性使用(更确切的说,在支持的浏览器中 Window
对象实现了 WindowLocalStorage
和 WindowSessionStorage
对象并挂在其 localStorage
和 sessionStorage
属性下)—— 调用其中任一对象会创建 Storage
对象,通过 Storage
对象,可以设置、获取和移除数据项。对于每个源(origin)sessionStorage
和 localStorage
使用不同的 Storage 对象——独立运行和控制。
例如,在文档中调用 localStorage
将会返回一个 Storage
对象;调用 sessionStorage
返回一个不同的 Storage
对象。可以使用相同的方式操作这些对象,但是操作是独立的。
一个简单的示例
为了展示 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() { var currentColor = localStorage.getItem('bgcolor'); var currentFont = localStorage.getItem('font'); var 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;
通过 StorageEvent 响应存储的变化
无论何时,Storage
对象发生变化时(即创建/更新/删除数据项时,重复设置相同的键值不会触发该事件,Storage.clear()
方法至多触发一次该事件),StorageEvent
事件会触发。在同一个页面内发生的改变不会起作用——在相同域名下的其他页面(如一个新标签或 iframe)发生的改变才会起作用。在其他域名下的页面不能访问相同的 Storage 对象。
在事件结果页面中的 JavaScript 如下所示(可见 events.js):
window.addEventListener('storage', function(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 = e.storageArea; });
这里,我们为 window 对象添加了一个事件监听器,在当前域名相关的 Storage
对象发生改变时该事件监听器会触发。正如你在上面看到的,此事件相关的事件对象有多个属性包含了有用的信息——改变的数据项的键,改变前的旧值,改变后的新值,改变的存储对象所在的文档的 URL,以及存储对象本身。
删除数据记录
Web Storage 提供了一对简单的方法用于移除数据。我们没用在我们的 demo 中使用这些方法,但是添加到你自己的项目中很简单:
Storage.removeItem()
接受一个参数——你想要移除的数据项的键,然后会将对应的数据项从域名对应的存储对象中移除。Storage.clear()
不接受参数,只是简单地清空域名对应的整个存储对象。
规范
Specification | Status | Comment |
---|---|---|
Web Storage (Second edition) | Recommendation |
浏览器兼容性
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari (WebKit) |
---|---|---|---|---|---|
localStorage | 4 | 3.5 | 8 | 10.50 | 4 |
sessionStorage | 5 | 2 | 8 | 10.50 | 4 |
Feature | Android | Firefox Mobile (Gecko) | IE Phone | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|
Basic support | 2.1 | ? | 8 | 11 | iOS 3.2 |
各浏览器支持的 localStorage 和 sessionStorage 容量上限不同。测试页面 detailed rundown of all the storage capacities for various browsers。
Note: since iOS 5.1, Safari Mobile stores localStorage data in the cache folder, which is subject to occasional clean up, at the behest of the OS, typically if space is short.