Web存储机制,在这里主要聊有关于Web Storage API提供的存储机制,通过该机制,浏览器可以安全地存储键值对,比使用cookie更加直观。接下来简单的了解如何使用这方面的技术。
基本概念
Web Storage 包含两种机制:
sessionStorage
为每一个给定的源维持一个独立的存储区域,该区域在页面会话期间可用(即只要浏览器处于打开状态,包括页面重新加载和恢复)localStorage
同样的功能,但是在浏览器关闭,然后重新打开后数据仍然存在
这两种机制是通过Window.sessionStorage
和Window.localStorage
属性使用。更确切的说,在支持的浏览器中Window
对象实现了WindowLocalStorage
和WindowSessionStorage
对象并挂在其localStorage
和sessionStorage
属性下。调用其中任一对象会创建Storage
对象,通过Storage
对象,可以设置、获取和移除数据项。对于每个源sessionStorage
和localStorage
使用不同的Storage
对象。
例如,在文档中调用localStorage
将会返回一个Storage
对象,调用sessionStorage
返回一个不同的Storage
对象。可以使用相同的方式操作这些对象,但是操作是独立的。
在了解如何使用localStorage
和sessionStorage
之前,先来一下Storage
对象。
Storage对象
Storage
对象作为Web Storage API的接口,Storage
提供了访问特定域名下的会话存储或本地存储的功能。例如,可以添加、修改或删除存储的数据项。
如果想操作一个域名的会话存储,可以使用Window.sessionStorage
;如果想要操作一个域名的本地存储,可以使用Window.localStorage
。
Storage对象的属性和方法
Storage
对象提供自己的属性和方法:
Storage.length
:返回一个整数,表示存储在Storage
对象中的数据项数量。这个是Storage
对象的一个属性,而且是一个只读属性。Storage.key()
:该方法接受一个数值n
作为参数,并返回存储中的第n
个键名Storage.getItem()
:该方法接受一个键名作为参数,返回键名对应的值Storage.setItem()
:该方法接受一个键名和值作为参数,将会把键值对添加到存储中,如果键名存在,则更新其对应的值Storage.removeItem()
:该方法接受一个键名作为参数,并把该键名从存储中删除Storage.clear()
:调用该方法会清空存储中的所有键名
简单的示例
写一个简单的示例,页面就三个按钮:Set
、Get
和Remove
。按钮点击时,分别绑定三个函数:setStorage()
、getStorage()
和removeStorage()
:
setStorage()
:做了localStorage
和sessionStorage
存储,同时存的键名为name
,键值为W3cplus.com
getStorage()
:取得存储的name
,并打印出来removeStorage()
:移除setStorage()
函数中存储的name
来看一下操作得到的效果。
首先点击Set
按钮。使用浏览器开发者工具,我们可以看到Local Storage
和Session Storage
都存了一个name
的键名,其对应的键值为W3cplus.com
。如下图所示:
Local Storage截图
Session Storage截图
这个时候点击Get
按钮,可以分别获取setStorage()
存的name
的值,并且输出:
接下来,再点击Remove
按钮,再次打开开发者工具,查看Local Storage
和Session Storage
选项,可以看到,当初对应的Key
和Value
被清空了,比如下面截图是Session Storage
:
这个时候,再次点击Get
按钮,输出的内容为null
:
上面我们看到的是第一种现象。我们再来看第二种。先点击Set
按钮,再点击Get
按钮,可以看到下面的输出的内容:
同样的页面,再不做Remove
按钮操作,直接把浏览器窗口关闭,然后重新加载页面,并且直接点击Get
按钮,看到的页面输出内容:
可以看出localStorage
输出的内容还是W3cplus.com
,而sessionStorage
输出的内容变成null
了。从这个效果也验证了前面提到的:sessionStorage
和localStorage
类似,允许你访问一个Storage
对象,只不过sessionStorage
访问的是一个session Storage
对象,而localStorage
访问的是一个local Storage
对象。另外不同之处在于localStorage
里面存储的数据没有过期的时间设置,而存储在sessionStorage
里面的数据在页面会话结束时会被清除。页面会话在浏览器打开期间一直保持,并且重新加载或恢复页面仍然会保持原来的页面会话。在新标签或窗口打开一个页面会初始化一个新的会话(localStorage
的key
的value
依旧保存,而sessionStorage
的key
的value
会被清除)。
本地存储基本用法
前面的示例也演示过了,接下来拿localStorage
来做示例:
localStorage.setItem('key', 'value'); // 设置一个localStorage,名称叫`key`
localStorage.getItem('key'); // 获取存储的localStorage,获取的`key`对应的值`value`
localStorage.removeItem('key'); // 移除存储的localStorage,删除的名称`key`
localStorage.clear(); // 删除所有的localStorage
为了方便使用,可以对其进行封装。
设置localStorage
function setLocalStorage(key, value) {
return localStorage.setItem(key, value);
}
获取localStorage
function getLocalStorage(key) {
return localStorage.getItem(key);
}
移除localStorage
function removeLocalStorage(key) {
return localStorage.removeItem(key);
}
注:sessionStorage
使用方法和localStorage
类似。
异常处理
localStorage
在目前的浏览器环境来说,还不是完全稳定的,可能会出现各种各样的问题,所以在设置localStorage
时一定要考虑异常处理。localStorage
的异常处理一般用try/catch
来捕获/处理异常。所以我们在设置localStorage
需要将try/catch
添加进来,所以前面的setLocalStorage()
函数可以修改成:
function setLocalStorage(key, value) {
try {
localStorage.setItem(key, value);
} catch (e) {
if (e.name === 'QUOTA_EXCEEDED_ERR' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
console.log("Error: Local Storage limit exceeds.");
localStorage.clear();
} else {
console.log("Error: Saving to local storage.");
}
}
}
如果考虑更具浏览器兼容性,我们还可以将上面的代码修改成:
function setLocalStorage(key, value) {
try {
localStorage.setItem(key, value);
} catch(e) {
if (isQuotaExceeded(e)) {
console.log("Error: Local Storage limit exceeds.");
localStorage.clear();
} else {
console.log("Error: Saving to local storage.");
}
}
}
function isQuotaExceeded(e) {
var quotaExceeded = false;
if (e) {
if (e.code) {
switch (e.code) {
case 22:
quotaExceeded = true;
break;
case 1014:
// Firefox
if (e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
quotaExceeded = true;
}
break;
}
} else if (e.number === -2147024882) {
// IE8
quotaExceeded = true;
}
}
return quotaExceeded;
}
过期时间
就localStorage
而言,其原生是不支持设置过期时间的,想要设置的话,就只能自己来封装一层逻辑来实现:
function setLocalStorage(key, value) {
var curtime = new Date().getTime(); // 获取当前时间
// 转换成JSON字符串序列
var valueDate = JSON.stringify({
val: value,
timer: curtime
});
try {
localStorage.setItem(key, valueDate); // 将JSON字符串设置为存储值
} catch(e) {
if (isQuotaExceeded(e)) {
console.log("Error: Local Storage limit exceeds.");
localStorage.clear();
} else {
console.log("Error: Saving to local storage.");
}
}
}
function isQuotaExceeded(e) {
var quotaExceeded = false;
if (e) {
if (e.code) {
switch (e.code) {
case 22:
quotaExceeded = true;
break;
case 1014:
// Firefox
if (e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
quotaExceeded = true;
}
break;
}
} else if (e.number === -2147024882) {
// IE8
quotaExceeded = true;
}
}
return quotaExceeded;
}
function getLocalStorage(key,exp){
var vals = localStorage.getItem(key); // 获取本地存储的值
var dataObj = JSON.parse(vals); // 将字符串转换成JSON对象
// 如果(当前时间 - 存储的元素在创建时候设置的时间) > 过期时间
var isTimed = (new Date().getTime() - dataObj.timer) > exp;
if (isTimed){
console.log("expires");
} else {
var newValue = dataObj.val;
}
return newValue;
}
这个时候我们调用:
setLocalStorage('name', 'hello, w3cplus.com!');
var localKey = getLocalStorage('name', 2);
console.log(localKey);
如果我们把exp
的时间修改一下:
setLocalStorage('name', 'hello, w3cplus.com!');
var localKey = getLocalStorage('name', 0);
console.log(localKey);
作用域名
(图片来自:https://segmentfault.com/a/1190000004121465)
这里的所说的作用域名不是指函数中的作用域。而且localStorage
存储的作用域。所以指的是如何隔离开不同页面之间的localStorage
。localStorage
只要在相同的协议、相同的主机名、相同的端口下,就能读取和修改到同一份localStorage
存储的数据。而sessionStorage
要比localStorage
更苛刻一些,除了协议、主机名、端口外,还要求在同一窗口下。
容量限制
对于localStorage
和sessionStorage
存储是有一定的限制的,目前业界基本上统一为5M
,要比cookies
的4K
大得多,一般情况已足够使用。如果存储的量大于最大值时,各浏览器都会抛出一个错误QUOTA_EXCEEDED_ERR
。
浏览器兼容性
到目前为止 Web Storage得到众多主流浏览器的支持,有关于浏览器对其支持度,可以通过Caniuse.com来查阅。
总结
最近在做造物节项目,碰到了本地存储的需求,以前从示接触过,为了能较好的理解和整明白Web本地存储的相关知识,花了点时间学习了相关的知识,并做了一些笔记。因为初学相关知识,不免其中有错误之处,如果有不对之处,还请同行大婶拍砖指正。另外特别推荐一篇@Mathias整理的一篇文章《How I detect and use localStorage》。能帮助大家更好的理解有关于localStorage
相关知识。如果你有更好的教程或经验,欢迎在下面的评论中与我们一起分享。
如需转载,烦请注明出处:https://www.w3cplus.com/javascript/web-storage.html