那年夏天 2019-06-21
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.sessionStorage
和Window.localStorage
属性(更准确的说,在支持的浏览器中,Window
对象实现了WindowLocalStorage
和WindowSessionStorage
对象,他们是由localStorage
和sessionStorage
挂起的)——调用其中任何一个,都会创建一个Storage
对象的实例,透过它,数据项目可以被设置,取回,和移除。每一个sessionStorage
和localStorage
的源都是用不同的存储对象——它们是分辨运作和被控制的。
所以,第一次在文档中调用localStorage
后,它会返回一个Storage
对象,调用sessionStorage
之后,他又会返回另一个Storage
对象。它们都可以用同一种方式进行操控,但是都是彼此独立的。
为了能使用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 }
你可以用相同的办法来测试sessionStorage
:storageAvailable('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
会在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事件会被触发。
规范 | 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 | 被影响的存储对象 |