灏天阁

本地数据存储

· Yin灏

cookie 是服务器保存在浏览器的一小段文本信息,浏览器每次向服务器发出请求,会携带 cookie 信息到服务器。cookie 常用于在本地记录用户信息,利用 cookie 可以改进用户体验。

cookie 字符串是一组名值对,名称和值之间以等号相连,名值对之间使用分号进行分割。值中不能包含分号,逗号,空格。如果包含特殊字符,应该使用 escape() 进行编码,在读取 cookie 时才使用 unescape() 函数进行解码。

  • cookie 信息字符串,包含一个名值对,默认为空。
  • cookie 有效期,包含一个 GMT 格式字符串,默认为当前会话期,即关闭浏览器时,cookie 信息就会过期。
  • cookie 有效路径,默认为 cookie 所在页面目录及其子目录。
  • cookie 有效域,默认为设置 cookie 的页面所在的域。
  • cookie 安全性,默认为不采用安全加密措施进行传递。

使用 document.cookie 可以读写 cookie 字符串信息。

// 存储 cookie 信息
var d = new Date();

d = d.toString();

console.log(d); // Thu Aug 12 2021 13:35:02 GMT+0800 (中国标准时间)

d = "date=" + escape(d);

console.log(d);

document.cookie = d;

如果要长久保存 cookie 信息, 可以设置 expires 属性,把字符串 “expires=date” 附加到 cookie 字符串后面,如下:

name = value;expires = date;
/*
  date 为格林威治日期时间(GMT),格式为 Sun, 30 Apr 2017 00:00:00 UTC
  使用 Date.toGMTString() 方法可以快速把事件转换为 GMT 格式。
*/

下面创建一个有效期为一个月的 cookie 信息

var d = new Date();
d.setMonth(d.getMonth() + 1); //  提取月份加 1,然后重新设置当前日期对象

d = "date=" + escape(d) + ";expires=" + d.toGMTString();

document.cookie = d;

cookie 信息是有 域 和 路径限制的,默认情况下,仅在当前页面路径内有效。

可以使用 cookie 的 path 和 domain 属性重设可见路径和作用域。其中 path 属性包含了与 cookie 信息相关联的有效路径,domain 属性定义了 cookie 信息的有效作用域。用法如下:

name=value;expires=date;domain=domain;path=path;

很多网站可能包含很多子域名,如:

http://www.baidu.com

默认情况下,cookie 只能在本域中访问,通过设置 cookie 的 domain 属性修改域的范围,例如在 http://www.baidu.com/index.html 中设置 cookie 的 domain 属性为 domain = tieba.baidu.com,就可以在 http://tieba.baidu.com 域下访问该 cookie。如果设置 cookie 的 domain = baidu.com,则所有子域名都可以访问。

// 把写入 cookie 信息的实现代码进行封装
/**
 * @param {cookie 名称} name 
 * @param {cookie 值} value 
 * @param {有效天数} expires 
 * @param {有效路径} path 
 * @param {域} domain 
 * @param {安全性设置, 是否加密传输} secure 
 */
function setCookie(name, value, expires, path, domain, secure) {
    var today = new Date();
    // today.getTime() 时间戳
    today.setTime(today.getTime()); // 设置现在时间
    if (expires) {
        expires = expires * 1000 * 60 * 60 * 24; // 转换为毫秒数
    }
    var expires_date = new Date(today.getTime() + expires); // 新建有效期时间对象
    document.cookie = name + "=" + escape(value) + (expires ? ";expires=" + expires_date.toGMTString() : "") + (path ? ";path=" + path : "") + (domain ? ";domain=" + domain : "") + (secure ? ";secure" : "");
}
// 将 cookie 字符串转换为对象类型
function getCookie() {
    var a = document.cookie.split(";");
    var o = {};
    for (var i = 0; i < a.length; i++) {
        var v = a[i].split("=");
        o[v[0]] = v[1];
    }
    return o;
}
// 指定 cookie 名,获取单个 cookie
// 多条 cookie
// "date=Sun%20Sep%2012%202021%2014%3A18%3A53%20GMT+0800%20%28%u4E2D%u56FD%u6807%u51C6%u65F6%u95F4%29; test1=1; test2=2"
function getCookie(name) {
    var start = document.cookie.indexOf(name + "="); // 提取与 cookie 名相同的字符串索引
    var len = start + name.length + 1; // 计算值的索引位置
    if (!start && name != document.cookie.substring(0, name.length)) { // 没有返回 null
        return null;
    }
    if (start == -1) return null;
    var end = document.cookie.indexOf(";", len);
    if (end == -1) end = document.cookie.length;
    return unescape(document.cookie.substring(len, end))
}

console.log(getCookie('test1')); // 1
function deleteCookie(name, path, domain) {
    if (getCookie(name)) {
        document.cookie = name + "=" + (path ? ";path=" + path : "") + (domain ? ";domain=" + domain : "") + ";expires=Thu, 01-Jan-1970 00:00:00 GMT";
    }
}
deleteCookie('test1');

浏览器对 cookie 信息有个数限制的,为了避免这个限制,可以把多条信息都保存在一个 cookie 中。

实现方式:

name=subName1:subValue1,subName2:subValue2,subName3:subValue3...

下面演示如何在 cookie 中存储更多信息:

var d = new Date();
d.setMonth(d.getMonth() + 1);
d = d.toGMTString();
var a = "name:a,age:20,addr:beijing";
var c = "user=" + escape(a);
c += (";expires=" + d);
document.cookie = c;

读取 cookie:

function getSubCookie()
{
    var a = document.cookie.split(";");
    var o ={};
    for (var i = 0; i < a.length; i ++ ) {
        a[i] && (a[i] = a[i].replace(/^\s+|\s+$/, ""));
        var b = a[i].split("=");
        var c = b[1];
        c && (c = c.replace(/^\s+|\s+$/, ""));
        c = unescape(c);
        if( ! /\,/gi.test(c)){
            o[b[0]] = b[1];
        } else {
            var d = c.split(",");
            for (var j = 0; j < d.length; j ++ )
            {
                var e = d[j].split(":");
                o[e[0]] = e[1];
            }
        }
    }
    return o;
}

设置 cookie 的时候,如果服务器加上了 HttpOnly 属性,则这个 cookie 无法被 JS 读取(即 document.cookie 不会返回这个 cooKie 的值),只用于向服务器发送。

Web Storage

  • localStorage: 用于持久化的本地存储,除非主动删除;否则数据永远不会过期。
  • sessionStorage: 用于存储本地会话(session)数据,这些数据只在同一个会话周期内访问,会话结束即被销毁。

遍历

var storage = window.localStorage;
for(var i = 0; len = storage.length; i < len; i++) {
    var key = storage.key(i);
    var value = storage.getItem(key);
    console.log(key + "=" + value);
}

监测事件

Web Storage 定义的 storage 事件,当键值改变或者调用 clear() 方法的时候,将触发 storage 事件。

监听本地存储,当发生值变动时,及时进行提示:

if(window.addEventListener) {
  window.addEventListener("storage", handle_storage, false);
} else if(window.attachEvent) {
  window.attachEvent('onstorage', handle_storage);
}

function handle_storage(e) {
  var logged = "key:" + e.key + ", newValue:" + e.newValue + ", oldValue:" + e.oldValue + ", url:" + e.url + ", storageArea:" + e.storageArea;
  console.log(logged);
}

- Book Lists -