HTML5
在客户端存储上推出的两种新方法。之前都是由cookie完成, 但是cookie并不适合做大量数据的存储,严重影响数据传输效率。但cookie能实现跨域(在请求上由请求决定),而他们不能,这里先不谈这点。
* Web存储有两种方式: localStorage 和 sessionStorage
localStorage定义
网上常解释:localStorage 用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期。总感觉还没明白,我理解是:localStorage 是一种持久化的存储,它能将数据存储到本地硬盘当中,因此数据没有时间限制,不会因为一次会话结束或关机等操作而消失,除非我们主动清除。
localStorage 的使用
localStorage
用 setItem()
方法来设置值,用 getItem()
方法获取值。
html代码
<div id="result"></div>
javascript代码
// 检查浏览器支持性
if ( typeof(Storage) && typeof(localStorage) ) {
// 添加值
localStorage.setItem("sayHi", "Hello World!");
// 取值
document.getElementById("result").innerHTML = localStorage.getItem("sayHi");
} else {
document.getElementById("result").innerHTML = "您的浏览器不支持 Web Storage ...";
}
效果展示
代码解释:
typeof(Storage)
将输出function
, typeof(localStorage)
将输出Object
,也有说要添加 typeof(window.localStorage)
的。增强检测,我觉得没太大必要。另外,localStorage
其实就是一个对象,因此我们存储,都是往这个对象中增加键值对而已。
localStorage数据的“全局性“
此处说全局性,大家可别以为是全局变量,这是不同的概念。localStorage的数据就数据本身来说,其实是脱离程序而存在的(磁盘中不同的程序所产生的localStorage会被分离存放,不会互相干扰),那么,它就不受程序作用域范围的限制,即,拥有全局性。既然如此,我们可以有以下用法:
统计用户页面访问次数
html代码
<div class="box">
<p>当前访问人次:<span id="views"></span></p>
<p>TIP:关闭或刷新,访问次数会增加。</p>
</div>
javascript代码
if (localStorage.views) {
localStorage.views = Number(localStorage.views) + 1;
} else {
localStorage.setItem("views", 1);
}
document.getElementById("views").innerHTML = localStorage.views;
效果展示
sessionStorage 定义
关于sessionStorage的解释都比较统一:sessionStorage方法 针对一个 session【会话】进行数据存储。当用户关闭浏览器窗口后,数据会被删除。sessionStorage数据信息是存储在内存中的。
sessionStorage 的使用
sessionStorage
与localStorage
的用法类似,也有setItem()
和 getItem()
。
下面我们来看一个案例
html代码
<div class="box">
<button id="click">点击计数</button>
<p>当前计数:<span id="views"></span></p>
</div>
javascript代码
if (sessionStorage.views) {
// todo
} else {
sessionStorage.setItem("views", 1);
}
document.getElementById("click").onclick = function() {
sessionStorage.views = Number(sessionStorage.views) + 1;
document.getElementById("views").innerHTML = sessionStorage.views;
}
效果展示
在该案例中,我们用dom操作给 views
绑定了点击事件,每次点击,增加一个计数,变量存放在session中。
验证什么是一次「会话」
看这个例子
html代码
<div class="box">
<button id="click">点击计数</button>
<p>当前访问人次:<span id="views"></span></p>
<p>TIP:刷新,访问次数会增加;关闭页面,访问次数会重置。</p>
</div>
javascript代码
if (sessionStorage.views) {
sessionStorage.views = Number(sessionStorage.views) + 1;
} else {
sessionStorage.setItem("views", 1);
}
document.getElementById("views").innerHTML = sessionStorage.views;
效果展示
所以说:一次会话是指:用户打开浏览器,点击多个超链接,访问Web服务器上的资源,然后关闭浏览器,整个过程称之为一次会话。也就是说,刷新不会提前关闭会话。
关于浏览器存储,大致就这些,接下来我们在看看浏览器缓存
* 应用缓存 - 浏览器缓存
什么是应用缓存?
「缓存」 就是当你打开一个网页时,浏览器会自动下载副本到本地电脑上,感觉就像是你“另存为“一个网页到某个地方。浏览器也不是把所有的网页都缓存到本地,一般html
或get请求
会缓存,而post
就不缓存。
控制是否缓存
1. 客户端是否需要缓存能够在服务器端的 响应头上控制,响应头告诉缓存器不要保留缓存,缓存器就不会缓存相应内容;
2. 如果请求信息是需要认证或者安全加密的,相应内容也不会被缓存;
HTML 5 缓存
HTML 5引入了应用缓存【Application Cache】,它能实现在没有因特网连接时进行访问。它有三个优势:
- 离线浏览 - 用户可以在应用离线时使用它们。
- 速度 - 已缓存资源加载速度更快。
- 减少服务器负载 - 浏览器将只从服务器上下载更新过或更改过的资源。
如果需要启用应用程序缓存,请在文档的<html>标签中包含 manifest 属性:
<DOCTYPE HTML>
<html manifest="demo.appcache">
...
</html>
如上指定了manifest的html文件将会被缓存,未对其进行指定的页面不被缓存。也可以在manifest文件中直接指定该页面。
manifest文件的建议拓展名为.appcache
。
请注意, manifest 文件需要配置正确的MIME-type,即"text/cache-manifest"
必须在 web
服务器上进行配置。
MANIFEST.appcache 文件
manifest 文件是简单的文本文件,结构非常简单,它告知浏览器什内容需要缓存,什么内容不需要缓存。
由以下三个部分构成:
- CACHE MANIFEST - 在此目录下列出的文件将在首次下载后进行缓存。
- NETWORK - 在此标题下列出的文件需要与服务器交互获取,不进行缓存。
- FALLBACK - 该标题下列出的文件规定当页面无法访问时的回退页面(比如404页面)
- manifest文件完整实例*:
CACHE MANIFEST
# 2012-02-21 v1.0.0
/theme.css
/logo.fig
/main.js
NETWORK:
login.html
FALLBACK:
/html5/ /404.html // 前者是资源URI, 后者是代替页面
【说明:】
- 以 # 开头的是注释行,但也可以满足其他需求。应用缓存会在器 manifest 文件被更改的时候更新。如果您编辑了一副图片,或者修改了一个javascript函数,这些改变都不会被重新缓存。这时候,更新注释行中的日期和版本号是一种使浏览器重新缓存文件的非常好的办法。
- NETWORK 可以使用星号来指示所有其他资源/文件都需要因特网连接,如
NETWORK:
*
- 更新缓存:
1. 用户在浏览器上自己清空缓存。
2. manifest 文件被修改。
3. 由程序来更新应用缓存。
经常遇到的困扰:
一旦文件被缓存,则浏览器会继续展示已缓存的版本。你可能会遇到,服务器上已经更新了代码,但浏览器依旧显示旧的内容,而且已经向CDN多次推新的资源也没用。 其实这时候就是因为浏览器缓存了的原因。你需要更新一下manifest
文件。一般浏览器设置的限制缓存是5M。
* 从浏览器角度看缓存
借用网络上的一张图片:
我们来细说两个校验参数:
Last-Modified 和 ETag
1. Last-Modified 工作原理
在浏览器第一次请求某一个URL时,服务器端的返回状态会是200,内容是你请求的资源,同时有一个Last-Modified
的属性标记(HttpReponse Header)
此文件在服务期端最后被修改的时间.
格式:Last-Modified:Tue, 24 Feb 2009 08:01:04 GMT
客户端第二次请求此URL时,根据HTTP协议的规定,浏览器会向服务器发送If-Modified-Since
报头(HttpRequest Header)
,询问该时间之后文件是否有被修改过:
格式:If-Modified-Since:Tue, 24 Feb 2009 08:01:04 GMT
如果服务器端的资源没有变化,则自动返回HTTP304(NotChanged.)
状态码,内容为空,这样就节省了传输数据量。当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求时类似。从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。
注:如果If-Modified-Since的时间比服务器当前时间(当前的请求时间request_time)还晚,会认为是个非法请求。
2. ETag 工作原理
HTTP协议规格说明定义ETag为“被请求变量的实体标记”,简单说即服务器响应时给请求URL标记,并在HTTP响应头中将其传送到客户端,类似服务器端返回的格式:
格式:Etag:“5d8c72a5edda8d6a:3239″
客户端的查询更新格式是这样的:
格式:If-None-Match:“5d8c72a5edda8d6a:3239″
如果ETag没改变,则返回状态304。
即:在客户端发出请求后,HttpReponse Header中
包含Etag:“5d8c72a5edda8d6a:3239″
标识,等于告诉Client端,你拿到的这个的资源有表示ID:5d8c72a5edda8d6a:3239。当下次需要发Request索要同一个URI的时候,浏览器同时发出一个If-None-Match报头(Http RequestHeader)此时包头中信息包含上次访问得到的Etag:“5d8c72a5edda8d6a:3239″标识。
格式:If-None-Match:“5d8c72a5edda8d6a:3239“
这样,Client端等于Cache了两份,服务器端就会比对2者的etag。如果If-None-Match为False,不返回200,返回304(Not Modified) Response。
就介绍这些,如果有错误,欢迎指正。