使用Web存储API

TODO:本文由 赤石俊哉 翻译整理,您可以将本文自由地用于学习交流。如需用于其他用途请征得作者的同意。
原文链接:Using the Web Storage API - Mozilla Developer Network (英文)


Web存储API提供了浏览器可以在本地安全存储键值对的一个机能,它比cookies更为直观。这篇文章将会简单阐述一下如何来简单地使用这种技术。

基础概念

存储对象是一个简单的键值存储,它跟对象类似,但是它们在页面读取后依然完整。键和值总是字符串(注意,整型数据也会自动地转为字符串,就像对象那样)。你可以像访问一个对象一样来访问这些值,或者使用方法:Storage.getItem()Storage.setItem()。下面这三行都是设置了colorSetting记录:

localStorage.colorSetting = '#a4509b';
localStorage['colorSetting'] = '#a4509b';
localStorage.setItem('colorSetting', '#a4509b');

Note: 强烈推荐使用Web存储API(setItem, getItem, removeItem, key, length)进行纯对象的键值操作来防止可能出现的隐患。

两种Web存储中包含的机能如下:

  • sessionStorage 为每一个页面访问session期间维持一个单独的存储空间(只要浏览器打开就一直维持,包括页面重载和重新存储)。

  • localStorage 做同样的事情,只不过在浏览器被关闭再打开后仍然维持着。

这些机能可以通过Window.sessionStorageWindow.localStorage属性(更准确的说,在支持的浏览器中,Window对象实现了WindowLocalStorageWindowSessionStorage对象,他们是由localStoragesessionStorage挂起的)——调用其中任何一个,都会创建一个Storage对象的实例,透过它,数据项目可以被设置,取回,和移除。每一个sessionStoragelocalStorage的源都是用不同的存储对象——它们是分辨运作和被控制的。

所以,第一次在文档中调用localStorage后,它会返回一个Storage对象,调用sessionStorage之后,他又会返回另一个Storage对象。它们都可以用同一种方式进行操控,但是都是彼此独立的。

localStorage 功能检测

为了能使用localStorage,我们应该先进行确认,当前的浏览器会话是否支持和允许使用它。

测试支持和可用性

如果浏览器支持localStorage,在它的window对象中就会有一个属性叫作localStorage。但是,由于种种原因,如果直接去断定这个属性是否存在可能会抛出异常。如果它确实存在,也没有保障我们就一定可以使用它,因为很多浏览器支持在设定中禁用localStorage。举个例子,那就是Safari,在隐私浏览模式下,他会给我们一个配额为0的空的localStorage对象,实际上就是使它无效化。我们在检测的时候,也应该把这一点考虑进来。

下面是一个用于检测localStorage是否支持以及可用的方法:

function storageAvailable(type) {
    try {
        var storage = window[type],
            x = '__storage_test__';
        storage.setItem(x, x);
        storage.removeItem(x);
        return true;
    }
    catch(e) {
        return false;
    }
}

你应该这样使用它:

if (storageAvailable('localStorage')) {
    // Yippee! We can use localStorage awesomeness
}
else {
    // Too bad, no localStorage for us
}

你可以用相同的办法来测试sessionStoragestorageAvailable('sessionStorage')

你可以参考一下localStorage功能检测简报(英文)

一个简单的例子

为了举例说明一些典型的Web存储用例,我们创建了一个简单的例子,叫它Web Storage Demo吧。登录页面提供了一个控件来自定义颜色,字体,和装饰图片:

当你选择不同的选项,页面会实时地更新,顺带一提,你的选项会被存储到localStorage里存储。所以当你离开页面重新载入它的时候,你的选择会被记住。

我们也提供了一个事件输出页面——如果你在另一个标签页中载入这个页面,那么你在登录页面中做出的任何选择之后,你会看到更新了的存储信息会被显示出来,因为StorageEvent被触发了。

Note: 你可以从这里查看源代码

检测你的数据是否被填充成功

拿上面的例子来说,在main.js中,我们将会测试存储对象是否已经被填入(也就是说页面是否之前就已经载入过了):

if(!localStorage.getItem('bgcolor')) {
  populateStorage();
} else {
  setStyles();
}

Storage.getItem()方法被用于从存储中获取数据项目。在这个例子中,我们测试bgcolor项目是否存在。如果不存在,我们运行populateStorage()来将已经存在的自定义值存入存储。如果已经有数据了,我们运行setStyle()以使用存储的值来更新页面的样式。

Note: 你也可以使用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在存储做出改变时进行响应

StorageEvent会在Storage对象发生变化时进行相应。它不能很好地在发生改变的页面上进行相应,但是在同一个域名的页面之间同步任何变化时,这是会是一个不错的方法。在不同的域名中无法访问相同的存储对象。

在事件页面(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对象,当当前源的存储对象发生改变时引发。就如你所能看见的,这个事件的参数包含了很多有用的信息——发生变化的键名,旧值,新值,发生变化的文档的URL,以及存储对象其自身。

删除数据记录

Web存储也提供了一对简单的方法来移除数据。在我们的demo中没有使用这些,把它们加到我们的项目里面来也不难。

  • Storage.removeItem()使用一个简单的参数(你想要移除的数据项目的键)来将它从域名下的存储对象中移除它。

  • Storage.clear()是一个无参方法,它会清空域名下所有的存储对象。

浏览器兼容性

桌面

特 性 Chrome Firefox(Gecko) Internet Explorer Opera Safari(Webkit)
localStorage 4 3.5 8 10.50 4
sessionStorage 5 2 8 10.50 4

移动

特 性 Android Firefox Mobile(Gecko) IE Phone Opera Mobile Safari Mobile
基础支持 2.1 ? 8 11 iOS 3.2

Storage 事件

当一个存储区域(本地存储和会话存储)被修改时,storage事件会被触发。

通用信息

规范 Web Storage
接口 StorageEvent
冒泡
可取消
目标 DefaultView(<window>)
默认动作

属性

属性 类型 描述
target readonly EventTarget 事件的目标(DOM树中最顶层的目标)
type readonly DOMString 事件的类型
bubbles readonly Boolean 事件是否冒泡(bubbles)
cancelable readonly Boolean 事件是否可以取消
key readonly DOMString(string) 被修改的键名
oldValue readonly DOMString(string) 旧的值
newValue readonly DOMString(string) 新的值
url readonly DOMString(string) 更新该键名的文档的地址
storageArea readonly Storage 被影响的存储对象

赤石俊哉
127 声望227 粉丝