Web 存储机制

栏目: Html5 · 发布时间: 7年前

内容简介:Web 存储机制

Web存储机制,在这里主要聊有关于Web Storage API提供的存储机制,通过该机制,浏览器可以安全地存储键值对,比使用cookie更加直观。接下来简单的了解如何使用这方面的技术。

基本概念

Web Storage 包含两种机制:

  • sessionStorage 为每一个给定的源维持一个独立的存储区域,该区域在页面会话期间可用(即只要浏览器处于打开状态,包括页面重新加载和恢复)
  • localStorage 同样的功能,但是在浏览器关闭,然后重新打开后数据仍然存在

这两种机制是通过 Window.sessionStorageWindow.localStorage 属性使用。更确切的说,在支持的浏览器中 Window 对象实现了 WindowLocalStorageWindowSessionStorage 对象并挂在其 localStoragesessionStorage 属性下。调用其中任一对象会创建 Storage 对象,通过 Storage 对象,可以设置、获取和移除数据项。对于每个源 sessionStoragelocalStorage 使用不同的 Storage 对象。

例如,在文档中调用 localStorage 将会返回一个 Storage 对象,调用 sessionStorage 返回一个不同的 Storage 对象。可以使用相同的方式操作这些对象,但是操作是独立的。

在了解如何使用 localStoragesessionStorage 之前,先来一下 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() :调用该方法会清空存储中的所有键名

简单的示例

写一个简单的示例,页面就三个按钮: SetGetRemove 。按钮点击时,分别绑定三个函数: setStorage()getStorage()removeStorage()

  • setStorage() :做了 localStoragesessionStorage 存储,同时存的键名为 name ,键值为 W3cplus.com
  • getStorage() :取得存储的 name ,并打印出来
  • removeStorage() :移除 setStorage() 函数中存储的 name

来看一下操作得到的效果。

首先点击 Set 按钮。使用浏览器开发者工具,我们可以看到 Local StorageSession Storage 都存了一个 name 的键名,其对应的键值为 W3cplus.com 。如下图所示:

Local Storage截图

Web 存储机制

Session Storage截图

Web 存储机制

这个时候点击 Get 按钮,可以分别获取 setStorage() 存的 name 的值,并且输出:

Web 存储机制

接下来,再点击 Remove 按钮,再次打开开发者工具,查看 Local StorageSession Storage 选项,可以看到,当初对应的 KeyValue 被清空了,比如下面截图是 Session Storage

Web 存储机制

这个时候,再次点击 Get 按钮,输出的内容为 null

Web 存储机制

上面我们看到的是第一种现象。我们再来看第二种。先点击 Set 按钮,再点击 Get 按钮,可以看到下面的输出的内容:

Web 存储机制

同样的页面,再不做 Remove 按钮操作,直接把浏览器窗口关闭,然后重新加载页面,并且直接点击 Get 按钮,看到的页面输出内容:

Web 存储机制

可以看出 localStorage 输出的内容还是 W3cplus.com ,而 sessionStorage 输出的内容变成 null 了。从这个效果也验证了前面提到的: sessionStoragelocalStorage 类似,允许你访问一个 Storage 对象,只不过 sessionStorage 访问的是一个 session Storage 对象,而 localStorage 访问的是一个 local Storage 对象。另外不同之处在于 localStorage 里面存储的数据没有过期的时间设置,而存储在 sessionStorage 里面的数据在页面会话结束时会被清除。页面会话在浏览器打开期间一直保持,并且重新加载或恢复页面仍然会保持原来的页面会话。在新标签或窗口打开一个页面会初始化一个新的会话( localStoragekeyvalue 依旧保存,而 sessionStoragekeyvalue 会被清除)

本地存储基本用法

前面的示例也演示过了,接下来拿 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);

Web 存储机制

如果我们把 exp 的时间修改一下:

setLocalStorage('name', 'hello, w3cplus.com!');
var localKey = getLocalStorage('name', 0);
console.log(localKey);

Web 存储机制

作用域名

Web 存储机制

( 图片来自:https://segmentfault.com/a/1190000004121465 )

这里的所说的作用域名不是指函数中的作用域。而且 localStorage 存储的作用域。所以指的是如何隔离开不同页面之间的 localStoragelocalStorage 只要在相同的协议、相同的主机名、相同的端口下,就能读取和修改到同一份 localStorage 存储的数据。而 sessionStorage 要比 localStorage 更苛刻一些,除了协议、主机名、端口外,还要求在同一窗口下。

容量限制

对于 localStoragesessionStorage 存储是有一定的限制的,目前业界基本上统一为 5M ,要比 cookies4K 大得多,一般情况已足够使用。如果存储的量大于最大值时,各浏览器都会抛出一个错误 QUOTA_EXCEEDED_ERR

浏览器兼容性

到目前为止 Web Storage得到众多主流浏览器的支持,有关于浏览器对其支持度,可以通过 Caniuse.com来查阅

Web 存储机制

总结

最近在做造物节项目,碰到了本地存储的需求,以前从示接触过,为了能较好的理解和整明白Web本地存储的相关知识,花了点时间学习了相关的知识,并做了一些笔记。因为初学相关知识,不免其中有错误之处,如果有不对之处,还请同行大婶拍砖指正。另外特别推荐一篇 @Mathias 整理的一篇文章《 How I detect and use localStorage 》。能帮助大家更好的理解有关于 localStorage 相关知识。如果你有更好的教程或经验,欢迎在下面的评论中与我们一起分享。

Web 存储机制

大漠

常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《 图解CSS3:核心技术与案例实战 》。


以上所述就是小编给大家介绍的《Web 存储机制》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Essential C++中文版

Essential C++中文版

李普曼 (Stanley B.Lippman) / 侯捷 / 电子工业出版社 / 2013-8-1 / CNY 65.00

本书以四个面向来表现C++的本质:procedural(面向过程的)、generic(泛型的)、object-based(基于对象的)、objectoriented(面向对象的)。全书围绕一系列逐渐繁复的程序问题,以及用以解决这些问题的语言特性来组织。循此方式,你将不只学到C++的功能和结构,也可学到它们的设计目的和基本原理。 本书适合那些已经开始从事软件设计,又抽不出太多时间学习新技术的程......一起来看看 《Essential C++中文版》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具