第23章 离线应用与客户端存储

支持离线web应用开发是HTML5的另一个重点。所谓离线web应用,就是在设备不能上网的情况下仍然可以运行的应用。

23.1 离线检测

if( navigator.onLine ){
    //正常工作
} else {
    //执行离线状态时的任务
}

为了更好的确定网络是否可用,HTML5还定义了两个事件:online和offline。当网络从离线变为在线或者从在线变为离线时,分别触发这两个事件。这两个事件在window对象上触发。

$(window).on('online', function(){
    alert('online')
})

$(window).on('offline', function(){
    alert('offline')
})

23.2 应用缓存

HTML5的应用缓存,简称 appcache ,是专门为开发离线web应用而设计的。Appcache 就是从浏览器的缓存中分出来的一块缓存区。

虽然应用缓存的意图是确保离线时资源可用,但也有相应的JS API让你知道它都在做什么。
这个API的核心是 applicationCache 对象,这个对象里有一个 status 属性,表示应用缓存的如下当前状态:

23.3 数据存储

随着 Web 应用程序的出现,也产生了对于能够直接在客户端上存储用户信息能力的要求。

23.3.1 Cookie

HTTP Cookie,通常直接叫做cookie,最初是在客户端用于存储会话信息的。

  1. 限制
    cookie有大小限制,超过限制,IE和Opera会删除最近最少使用过的cookie,腾出空间给新cookie。Firefox会随机删除cookie,所以限制cookie非常重要,以免出现不可预期的后果。

  2. cookie的构成
    (1) 名称:一个唯一确定cookie的名称,不区分大小写,名称必须是经过URL编码的。
    (2) 值:存储在cookie中的字符串值,值必须被URL编码
    (3) 域:cookie对于哪个域是有效的。所有向该域发送的请求中都会包含这个cookie信息,默认为设置cookie的那个域。
    (4) 路径:对于指定域中的那个路径,应该向服务器发送cookie
    (5) 失效时间:表示 cookie 何时应该被删除的时间戳(也就是说,何时应该停止向服务器发送这个cookie)。默认情况下,浏览器会话结束时即将所有 cookie 删除;
    (6) 安全标志:指定后, cookie只有在使用SSL连接的时候才发送到服务器。

  3. JavaScript 中的 cookie
    document.cookie 返回当前页面可用的所有 cookie 的字符串,一系列由分号隔开的名值对儿。
    所有名字和值都是经过 URL 编码的,所以必须使用 decodeURIComponent() 来解码

JS中基本的 cookie 操作有三种:读取、写入和删除,可以包装成下面函数:

var CookieUtil = {
    get: function (name){
        var cookieName = encodeURIComponent(name) + '=',
            cookieStart = document.cookie.indexOf(cookieName),
            cookieValue = null;
        if ( cookieStart > -1 ){
            var cookieEnd = document.cookie.indexOf(';', cookieStart);
            if( cookieEnd == -1 ){
                cookieEnd = document.cookie.length;
            }
            cookieValue = decodeURIComponent(document.cookie.substring( cookieStart + cookieName.length, cookieEnd));
        }
        return cookieValue;
    },
    set: function(name, value, expires, path, domain, secure){
        var cookieText = encodeURIComponent(name) + '=' + 
                         encodeURIComponent(value);
        if( expires instanceof Date ){
            cookieText += "; expires=" + expires.toGMTString();
        }
        if( path ){
            cookieText += "; path=" + path;
        }
        if( domain ){
            cookieText += "; domain=" + domain;
        }
        if( secure ){
            cookieText += '; secure';
        }
        document.cookie = cookieText;
    },
    unset: function(name, path, domain, secure){
        this.set(name, "", new Date(0), path, domain, secure);
    }
}
  1. 子cookie

  2. 关于cookie的思考
    cookie的性质和它的局限性使得其并不能作为存储大量信息的理想字段,所以又有其他方法。
    由于cookie的开放访问性,所以不能在cookie中存储重要和敏感的数据。

23.3.3 Web存储机制

Web Storage的目的是克服由 cookie 带来的一些限制,当数据需要被严格控制在客户端上时,无须持续地将数据发回服务器。Web Storage的两个主要目标是:
(1) 提供一种在 cookie 之外存储会话数据的途径;
(2) 提供一种存储大量可以跨会话存在的数据的机制。

  1. Storage 类型

有如下方法:

clear():删除所有值。
getItem(name):根据指定的名字name获取对应的值。
key(index):获得index位置处的值的名字。
removeItem(name):删除由name指定的名值对儿。
setItem(name, value):为指定的name设置一个对应的值。
  1. sessionStorage 对象
    sessionStorage 对象存储特定于某个会话的数据,也就是该数据只保持到浏览器关闭。这个对象就像会话 cookie,也会在浏览器关闭后消失。存储在 sessionStorage 中的数据可以跨越页面刷新而存在。

sessionStorage对象是 Storage 的一个实例

存储数据:
//使用方法存储数据
sessionStorage.setItem('name', 'Nick');

//使用属性存储数据
sessionStorage.book = 'JavaScript Book';

读取数据
//使用方法读取数据
var name = sessionStorage.getItem('name');

//使用属性读取数据
var book = sessionStorage.book;

删除数据
//使用 delete 删除一个值-在webkit中无效
delete sessionStorage.name;

//使用方法删除一个值
sessionStorage.removeItem('book');

使用循环迭代出sessionStorage中数据:

for (var i = 0, len = sessionStorage.length; i < len; i++){
     var key = sessionStorage.key(i);
     var value = sessionStorage.getItem(key);
     console.log(key + '=' + value);
}

sessionStorage对象主要用于仅针对会话的小段数据的存储。如果需要跨越会话存储数据,那么 globalStorage 或者 localStorage 更为合适。

  1. localStorage 对象
    localStorage 对象在修订过的 HTML5 规范中做为持久保存客户端数据的方案取代了 globalStorage。

由于 localStorage 是 Storage 的实例,所以可以有以下方法:

//使用方法存储数据
localStorage.setItem('name', 'Nick');

//使用属性存储数据
localStorage.book = 'JavaScript book';

//使用方法读取数据
var name = localStorage.getItem('name');

//使用属性读取数据
var book = localStorage.book;

存储在 localStorage 中的数据会保留到通过 JavaScript 删除或者是用户清除浏览器缓存。

由于有的浏览器只兼容 globalStorage,所以可以有以下兼容方案:

function getLocalStorage(){
   if ( typeof localStorage == "object" ){
        return localStorage;
   } else if( typeof globalStorage == "object" ){
        return globalStorage[location.host];
   } else {
        throw new Error('Local storage not available');
   }
}

var storage = getLocalStorage();
  1. storage 事件
    对 Storage 对象进行任何修改,都会在文档上触发 storage 事件
$(document).on('storage', function(event ){
})

无论是对 sessionStorage、globalStorage还是localStorage进行操作,都会触发 storage 事件,但不区分。

23.3.4 IndexedDB
是在浏览器中保存结构化数据的一种数据库,IndexedDB的思想是创建一套 API,方便保存和读取 JS对象,同时还支持查询及搜索。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容