Web应用允许使用浏览器提供的API实现将数据存储到用户的电脑上。这种客户端存储相当于赋予了Web浏览器记忆能力。
客户端存储遵循“同源策略”,因此不同站点的页面时无法互相读取对方存储的数据,而同一站点的不同页面之间是可以互相共享存储数据的,他为我们提供了一种通信机制。
客户端存储包括Web存储(localStorage与sessionStorage)、cookie、IE User Data、离线Web应用、Web数据库、文件系统API。
其他暂时不介绍,今天就介绍Web存储以及cookie。
Web储存优点多,但是对于早期浏览器并不兼容。
cookie使用所有新旧浏览器,但是其API非常复杂,能蕴藏的信息量少,而且每次Http请求都得带这些数据到服务器,占用了带宽。
但是,本文章记录的客户端存储不应该用来保存敏感信息,因为所有数据都是未加密形式的,可以被计算机任何有访问权限的人访问。
localStorage和sessionStorage是window的对象。
localStorage和sessionStorage的主要区别在于存储的有效期和作用域:数据可以存储多长时间以及谁拥有数据的访问权。
Web存储让我们可以存储结构化的数据(对象和数组),但是如果不能,也可以用另外一种方法(JSON)。
localStorage.data = JSON.stringify(data);
var data = JSON.parse(localStorage.data);
对于存储有效期来说,
localStorage存储的数据是永久性的,除非Web应用刻意删除存储的数据,或者用户通过设置浏览器配置来删除,否则数据一致存在。
sessionStorage存储的数据只是在会话期间,比如窗口或者标签页被永远关闭了,那么所有通过sessionStorage存储的数据也都被删除了。
对于作用域来说,
localStorage的作用域是限定在文档源级别的,文档源由协议、主机名以及端口三者来确定的。同源的文档间共享同样的localStorage数据。但是不同浏览器会有所限制。
sessionStorage的作用域也是限定在文档源中,因此非同源文档之间是无法共享的,另外它还被限制在窗口中。
localStorage和sessionStorage通常被当做普通的JavaScript对象使用,通过设置属性来存储字符串值,查询该属性来读取该值。但是,还有更正式的API。
localStorage.setItem("x", 1); // 以"x"的名字存储一个数值
localStorage.getItem("x");
localStorage.removeItem("x");
localStorage.clear();
localStorage.key(i);
对象和数组类型的值通常是可变的,因此存储对象要求存储他们的副本,以确保之后任何对这类对象的改变都不影响到存储的对象。
无论什么时候存储在localStorage或者sessionStorage的数据发生改变,浏览器都会在其他对该数据可见的窗口对象上触发存储事件(但是,在对数据进行改变的窗口对象上是不会出发的。)
与存储事件相关的事件对象有5个较为重要的属性:
key
被设置或者被移除的项的名字或者键名
newValue
保存该项的新值
oldValue
改变或者删除该项前,保存的值
storageArea
好比目标对象上的localStorage或者sessionStorage属性
url
触发该存储变化脚本所在本当的URL
localStorage和存储事件使采用广播机制的
存储的是数组字符串化后的字符串
cookie是指Web浏览器存储的少量数据,同时它是与具体的Web页面或者站点相关的。
cookie可以直接通过对Document对象的cookie属性来进行操作。
检测cookie是否启用: navigator.cookieEnabled = true
除了名(name)和值(value),cookie还有一些可选的属性来控制cookie的有效期和作用域。
有效期
cookie默认的有效期就在Web浏览器的会话期间(但这和sessionStorage不同,cookie的有效期与整个浏览器的进程而不是单个浏览器窗口的有效期一致)。但是可以通过设置max-age属性,明确高数浏览器cookie的有效期是多长(单位是秒)。一旦设置了有效期,浏览器就会将cookie数据存储在一个文件中,直到过了指定的有效期才会删除该文件。
作用域
cookie的作用域是通过文档源和文档路径来确定的。该作用域通过cookie的path和domain属性也是可配置的。默认情况下,cookie和创建它的Web页面有关,并对该Web页面以及和该Web页面同目录或者子目录的其他Web页面课件。
cookie的path属性不能被用做访问控制机制,如果一个Web页面想要读取同一站点其他页面的cookie,只要简单地把其他页面以隐藏
的形式加载进来,然后直接读取就可以。同源策略限制了跨站的cookie窥探,但是对于同一站点它是完全合法的。
cookie有个secure属性,那么只有当浏览器和服务器通过HTTPS或者其他的安全协议连接的时候才能传递它。
因为cookie中值是不允许包含分号、逗号和空白符,因此,在存储之前一般可以采用JavaScript核心的全局函数encodeURIComponent()对值进行编码,读取的时候需要采用decodeURIComponent()函数解码。
function setCookie(name, value, expire) {
var cookie = name + '=' + encodeURIComponent(value);
if (typeof expire === "number")
cookie += "; max-age=" + (expire*60*60*24);
document.cookie = cookie;
}
使用JavaScript来直接读取cookie时,返回的值是一个字符串,包含所有作用在当前文档的cookie。
function getCookie() {
var cookie = {};
var all = document.cookie;
if (all === "")
return cookie;
var list = all.split("; ");
for (var i = 0; i < list.length; i++) {
var cookie = list[i];
var p = cookie.indexOf("=");
var name = cookie.substring(0, p);
var value = cookie.substring(p + 1);
value = decodeURIComponent(value);
cookie[name] = value;
}
return cookie;
}
1.每次http请求都要发cookie
2.cookie容量很小
3.每个浏览器能存储的cookie个数有限
“应用程序缓存”是HTML5新增的内容,允许Web应用将应用程序自身本地保存到用户浏览器中。
它不会随着用户清楚浏览器缓存而被清楚。
用法如下:
// myapp.appcache包含所有应用程序依赖的所有URL列表
"myapp.appcache">
// myapp.appcache
CACHE MANIFEST
# 上一行标识此文件是一个清单文件。本行是注释
# 下面的内容都是应用程序依赖的资源文件的URL
myapp.html
myapp.js
myapp.css
images/background.png
PS:Web服务器识别清单文件的方式是通过”text/cache-manifest”这个MIME类型
复杂的清单
有三个区域:
1.CACHE:
这块是上例简单缓存的区域。
2.FALLBACK:
区域中每个清单项包含两个URL(比如videos/offline_help.html
),如果前一个载入失败,就会用第二个缓存资源来代替。
3.NETWORK:
该区域中的URL资源从不缓存,始终通过网络获取。支持”*”通配符。
在线状态下,浏览器会根据清单文件来检查更新,但是不会根据清单文件内容是否有变化来检查更新。
比如
CACHE MANIFEST
# MyApp version 1 (更改这个数字以便让浏览器重新下载这个文件)
MyApp.html
MyApp.js
Window对象下有个applicationCache对象,在浏览器更新缓存的过程中会触发一系列的事件。
applicationCache
事件
onupdateready 更新结束
onchecking 应用程序载入时检查清单文件
onnoupdate 清单文件没有改动
ondownloading 下载过程开始
onprogress 文件下载完毕时
oncached 下载完成并首次将应用程序下载到缓存中时
onerror 发生错误
onobsolete 引用一个不存在的清单文件
属性
UNCACHED(0) 应用程序未设置manifest属性
IDLE(1) 清单文件已检查完毕
CHECKING(2) 正在检查清单文件
DOWNLOADING(3) 浏览器正在下载并缓存清单中列举的所有文件
UPDATEREADY(4) 已下载
OBSOLETE(5) 清单文件不存在,缓存将被清楚
方法
update() 显式检测
swapCache() 告诉浏览器放弃旧缓存,使用新缓存
最简单的场景:游戏将积分最高玩家的名字上传到服务器上。
Web应用得navigator.online属性可检测是否联网。