使用Web存储API存取本地数据

那年夏天 2019-06-21

使用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吧。登录页面提供了一个控件来自定义颜色,字体,和装饰图片:

使用Web存储API存取本地数据

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

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

使用Web存储API存取本地数据

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()是一个无参方法,它会清空域名下所有的存储对象。

浏览器兼容性

桌面

特 性ChromeFirefox(Gecko)Internet ExplorerOperaSafari(Webkit)
localStorage43.5810.504
sessionStorage52810.504

移动

特 性AndroidFirefox Mobile(Gecko)IE PhoneOpera MobileSafari Mobile
基础支持2.1?811iOS 3.2

Storage 事件

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

通用信息

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

属性

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

相关推荐