Client_Storage

客户端存储方式的异同

客户端存储方式有:cookie、sessionStorage、localStorage、Web Storag等。

共同点: 都是保存在浏览器端,且有同源限制。

区别:

  1. cookie数据在浏览器和服务器间来回传递,和服务器端进行交互的,一般用于标识用户身份。而sessionStorage和localStorage用于浏览器缓存数据,不会自动把数据发给服务器,在本地保存。
  2. 由于Cookie是作为HTTP规范的一部分存在的,每次携带都会在HTTP头中,如果Cookie保存过多数据会带来性能问题,而WebStorage仅在客户端保存,不参与服务器的通信。一般浏览器不会修改cookie,但是会频繁操作cookie.
  3. cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下。
  4. 存储大小限制也不同,cookie数据不能超过4k,同时因为每次http请求都会携带cookie,所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,一般为5M左右。
  5. 数据有效期不同,sessionStorage仅在当前浏览器窗口关闭前有效,刷新页面后数据依旧存在,但关闭页面或关闭浏览器后就清除了,自然也就不可能持久保持;localStorage则是持久化的本地存储,除非被清除掉否则永久保存,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。
  6. 作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。
  7. Web Storage 支持事件通知机制(storage事件),可以将数据更新的通知发送给监听者。Web Storage 的 api 接口使用更方便。(注:Web Storage实际上由两部分组成:sessionStorage与localStorage。)

如何用JavaScript操作CookieWebStorage?

操作WebStorage

Cookie的操作需要自己封装getCookie,setCookie等,而Web Storage拥有setItem, getItem等方法可以使用,比如:
localStorage.setItem(“a”,”xxxxxx”); //设置
localStorage.getItem(“a”); //获取a的值
localStorage.removeItem(“a”); //删除a的值
document.cookie = “username=hyc”;

操作Cookie

在 JavaScript 中通过 document.cookie属性,你可以创建、维护和删除 Cookie。创建 Cookie 时该属性等同于 Set-Cookie 消息头,而在读取 Cookie 时则等同于 Cookie 消息头。在创建一个 Cookie 时,你需要使用和 Set-Cookie 期望格式相同的字符串:

1
document.cookie="name=Nicholas;domain=nczonline.net;path=/";

设置 document.cookie属性的值并不会删除存储在页面中的所有 Cookie。它只简单的创建或修改字符串中指定的 Cookie。下次发送一个请求到服务器时,通过 document.cookie设置的 Cookie 会和其它通过 Set-Cookie 消息头设置的 Cookie 一并发送至服务器。这些 Cookie 并没有什么明确的不同之处。要使用 JavaScript 提取 Cookie 的值,只需要从 document.cookie 中读取即可。返回的字符串与 Cookie 消息头中的字符串格式相同,所以多个 Cookie 会被分号和字符串分割。例如:name1=Greg; name2=Nicholas
鉴于此,你需要手工解析这个 Cookie 字符串来提取真实的 Cookie 数据。当前已有许多描述如何利用 JavaScript 来解析 Cookie 的资料,包括我的书,Professional JavaScript,所以在这我就不再说明。通常利用已存在的 JavaScript 库操作 Cookie 会更简单,如使用 YUI Cookie utility 来处理 Cookie,而不要手工重新创建这些算法。
通过访问 document.cookie返回的 Cookie 遵循发向服务器的 Cookie 一样的访问规则。要通过 JavaScript 访问 Cookie,该页面和 Cookie 必须在相同的域中,有相同的 path,有相同的安全级别。

注意:一旦 Cookie 通过 JavaScript 设置后便不能提取它的选项,所以你将不能知道 domain,path,expires 日期或 secure 标记。

从JavaScript的角度看,Cookie 就是一些 字符串String类型 信息。Cookie里面包含的信息并没有一个标准的格式,各个网站服务器的规范都可能不同,但一般会包括:所访问网站的域名(domain name),访问开始的时间,访问者的IP地址等客户端信息,访问者关于这个网站的一些设置等等。Cookie一般包含一下几个属性:name(名字),value(值),domain(域),path(路径),expires(过期时间);其中,name和value是必须的,其他的会有默认值。domain的默认值是当前页面的域名,path的默认值是当前页的URL,expires的默认值是Session(会话结束时清除Cookie)。

  1. 写入Cookie

写入Cookie主要设置五个字段,内容、有效期、域名、路径、是否安全传输。Cookie使用类似键值对的方式进行存储,比如“username=zhangshan”,只需将这个Cookie赋值给document.Cookie即可。名、值都要是标准的标识符,所以可以在使用前,用escape函数包裹,以免出错。document.cookie 有读和写两种形式,写形式代表添加Cookie,且一次只能添加一条Cookice,要添加多条则需要调用多次。处于安全性的考虑,Cookie是具有不可跨域性的,只有与创建 Cookie 的页面在同一个目录或子目录下的网页才可以访问.把Cookie设置为secure,那么它与服务器之间就通过HTTPS或者其它安全协议传递数据。c只保证 Cookie 与服务器之间的数据传输过程加密,而保存在本地的 Cookie文件并不加密。如果想让本地Cookie也加密,得自己加密数据。

1
2
3
document.cookie= "name=zhangsan;expires="+date.toGMTString();
//例如 "www.qq.com" 与 "sports.qq.com" 公用一个关联的域名"qq.com",我们如果想让 "sports.qq.com" 下的`Cookie`被 "www.qq.com" 访问,我们就需要用到 `Cookie` 的domain属性,并且需要把path属性设置为 "/"。
document.cookie= "name=zhangsan;domain=qq.com;secure";

  1. 读取Cookie

读取Cookie使用到document.Cookie的读模式,返回的就是所有的Cookie,中间用分号隔开。

1
2
3
document.cookie= "name=zhangsan";  //写
document.cookie= "age=10"; //写
console.log(document.`Cookie`); //输出 name=zhangsan; age=10

  1. 删除、修改Cookie

Cookie并不提供删除、修改的方法,如果想修改某项Cookie,只需添加一个同名Cookie,新的值将覆盖旧的值。要删除Cookie,只需将该Cookie有效期设置到当前时间以前即可。

1
2
3
4
5
6
7
document.cookie= "name=zhangsan";
document.cookie= "name=lisi"; //name被修改为lisi
var date = new Date();
//设置为前一毫秒(多前都可以)
date.setTime(date.getTime() - 1);
//删除name
document.cookie= "name=lisi;expires=" + date.toGMTString();

  1. 封装操作Cookie的方法

使用原生方法对Cookie操作是有些麻烦的,我们可以将其封装起来,name代表键名,value代表值,不填则为读取名为name的值,option代表设置值如有效期等。其中有效期单位为天。

客户端存储 VS 客户端缓存

通过chrome://cache/可以查看客户端缓存(浏览器文件缓存),文件缓存主要用来减少网络请求,提高页面加载速度的。包括你看的视频啊各种资源。除非手动永久删除,不然过期也还是在。

客户端存储就是一种存储技术,用来存取用户上网过程中的一些信息数据,和减少网络请求,提高页面加载速度没关系,就是存取状态的,数据可以用JS操作。比如:cookie用来标识用户有没有登陆;用户没有发出去的微博,也可以说是页面的状态数据,存在localStorage中,下次打开微博还在。缓存数据(数据库) !== 缓存

LocalStorage在浏览器多标签之间通信中的应用

localStorage 会触发一个事件。不论某个标签页在何时添加、修改或删除了 localStorage,都会对其余的所有标签触发事件,所有其它的标签页都能通过 window 对象监听到这个事件。这就意味着我们只要为 localStorage 赋值,通过监听事件,控制它的值,就能够跨浏览器标签通信了。使用localStorage.setItem(key,value);添加内容,使用storage事件监听添加、修改、删除的动作。
注意quirks:Safari 在无痕模式下设置localstorge值时会抛出 QuotaExceededError 的异常。
localStorage_event对象属性

1
2
3
window.addEventListener('storage', function (event) {
console.log(event.key, event.newValue);
});

例子:用户打开了两个标签页,在其中一个里执行了注销操作后返回另一个时,页面将重新载入,(如果可以的话)服务器端逻辑将把用户重定向到其它位置。这个检查只在当前标签页获得焦点时执行,这是因为用户可能在注销后立刻重新登录,这种情况下不应将其余标签页的状态全部设为已注销。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var loggedOn;
// call when logged-in user changes or logs out
logonChanged();
window.addEventListener('storage', updateLogon);
window.addEventListener('focus', checkLogon);
function getUsernameOrNull () {
// return whether the user is logged on
}
function logonChanged () {
var uname = getUsernameOrNull();
loggedOn = uname;
localStorage.setItem('logged-on', uname);
}
function updateLogon (event) {
if (event.key === 'logged-on') {
loggedOn = event.newValue;
}
}
function checkLogon () {
var uname = getUsernameOrNull();
if (uname !== loggedOn) {
location.reload();
}
}

参考: