离线应用和客户端存储

//region离线检测
    //判断设备是否能上网 navigator.onLine  window事件online offline
    //alert( navigator.onLine );

//监测网络变化
    W.addHandler( window, "online", function () {
        alert( "online" );
    } );
    W.addHandler( window, "offline", function () {
        alert( "offline" );
    } );
    //endregion

//region应用缓存 描述文件 manifest file P627

//endregion

//region 数据存储

//HTTP cookie
    //该标准要求服务器对任意HTTP请求发送Set-Cookie HTTP头作为相应的一部分,其中包括会话信息

//1.限制
    //cookie在性质上是绑定在特定的域名下的。
    // 当设定了一个cookie后,再给创建他的域名发送请求时,都会包含这个cookie。
    // 这个限制确保了存储在cookie中的信息只能让批准的接受者访问,而无法被其他域访问
    //cookie在客户端计算机大小和数量都有限制 根据浏览器不同单个域下最多20-50个 整个cookie长度限制在2095b

//2.cookie的构成  只有名值对儿才会被发送到服务器 其他参数都是服务器给浏览器的指示
    // 名称name  需要经过URL编码
    // 值value
    // 域domain
    // 路径path
    // 失效时间expires
    // 安全标志secure

//设置了secure标志的cookie只能通过SSL加密连接才能传输

//设置在HTTP头部分
    // HTTP/1.1 200 OK
    //Content-type:text/html
    //Set-Cookie:name-value;expires=Mon,22-Jan-07 07:10:24 GMT;domain=.wrox.com;path=/;secure
    //Other-header:other-header-value

//3.JavaScript中的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; //并不会覆盖原来的cookie 除非名称已经存在
        },

unset : function ( name, path, domain, secure ) {
            this.set( name, "", new Date( 0 ), path, domain, secure );
        }
    };

CookieUtil.set( "name", "zodiac", new Date( "January 1,2020" ) );

//CookieUtil.unset("name");
    //alert( CookieUtil.get( "name" ) );

//4.子cookie 为了绕开浏览器对单域名下的cookie的限制,使用子cookie name=name1=value1=&name2=value2 自由操作 但是这样会增加cookie的长度

var SubCookieUtil = {

get : function ( name, subName ) {
            var subCookies = this.getAll( name );
            if ( subCookies ) {
                return subCookies[subName];
            }
            else {
                return null;
            }
        },

getAll : function ( name ) {
            var cookieName = encodeURIComponent( name ) + "=",
                    cookieStart = document.cookie.indexOf( cookieName ),
                    cookieValue = null,
                    cookieEnd,
                    subCookies,
                    i,
                    parts,
                    result = {};
            if ( cookieStart > -1 ) {
                cookieEnd = document.cookie.indexOf( ";", cookieStart );

if ( cookieEnd == -1 ) {
                    cookieEnd = document.cookie.length;
                }

cookieValue = document.cookie.substring( cookieStart + cookieName.length, cookieEnd );

if ( cookieValue.length > 0 ) {
                    subCookies = cookieValue.split( "&" );

for ( i = 0, len = subCookies.length; i < len; i++ ) {
                        parts = subCookies[i].split( "=" );
                        result[decodeURIComponent( parts[0] )] = decodeURIComponent( parts[1] );
                    }

return result;
                }
            }
        },

set : function ( name, subName, value, expires, path, domain, secure ) {

var subCookies = this.getAll( name ) || {};
            subCookies[subName] = value;
            this.setAll( name, subCookies, expires, path, domain, secure );
        },

setAll : function ( name, subCookies, expires, path, domain, secure ) {

var cookieText = encodeURIComponent( name ) + "=",
                    subCookieParts = new Array(),
                    subName;

for ( subName in subCookies ) {
                if ( subName.length > 0 && subCookies.hasOwnProperty( subName ) ) {
                    subCookieParts.push( encodeURIComponent( subName ) + "=" + encodeURIComponent( subCookies[subName] ) );
                }
            }

if ( subCookieParts.length > 0 ) {
                cookieText += subCookieParts.join( "&" );

if ( expires instanceof  Date ) {
                    cookieText += ";expires=" + expires.toGMTString();
                }

if ( path ) {
                    cookieText += ";path=" + path;
                }

if ( domain ) {
                    cookieText += ";domain=" + domain;
                }

if ( secure ) {
                    cookieText += ";secure";
                }
            }
            else {
                cookieText += ";expires=" + (new Date( 0 )).toGMTString();
            }

document.cookie = cookieText;
        },

unset : function ( name, subName, path, domain, secure ) {
            var subCookies = this.getAll( name );

if ( subCookies ) {
                delete subCookies[subName];
                this.setAll( name, subCookies, null, path, domain, secure );
            }
        },

unsetAll : function ( name, path, domain, secure ) {
            this.setAll( name, null, new Date( 0 ), path, domain, secure );
        }

};

//endregion

//region Web存储机制

//Storage类型 HTML5 Storage类型都有公共方法setItem getItem removeItem key 大小限制根据浏览器2.5M--5M

//1.sessionStorage保持到会话结束,即保存到浏览器关闭 合适会话类的小段数据

sessionStorage.setItem( "name", "zodiac" );//使用方法存储数据
    sessionStorage.age = "22";//使用属性存储数据
    var name = sessionStorage.getItem( "name" );//使用方法获取数据
    var age = sessionStorage.age;//使用属性获取数据
    //sessionStorage.removeItem("name");
    //delete sessionStorage.age     使用delete删除一个值 在Webkit中无效
    // W.log( sessionStorage.key( 0 ) );//逆序获取指定位置上的名字

//2.localStorage HTML5标准 老版本使用globalStorage 跨会话第存储数据,但有特定的访问限制
    // globalStorage需要指定那些域可以访问该数据
    // 要访问localStorage页面必须来自同一域名(子域名无效),同一协议,同一端口上。相当于globalStorage[location.host]
    //两者的数据都保存到通过JavaScript删除或者用户清除浏览器缓存为止

//兼容
    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 localStorage = getLocalStorage();

localStorage.setItem( "name", "zodiac" );
    //Storage事件 ie8和FireFox只实现了domain属性 WebKit不支持此事件
    // 为Storage对象进行任何修改,都会在文档上触发storage事件 set get remove delete等都会触发
    W.addHandler( document, "storage", function ( event ) {
        var domain = event.domain,
                key = event.key,
                newValue = event.newValue,
                oldValue = event.oldValue;
    } );

//endregion

  //region IndexedDB

//IndexedDB思想是创建一套API,方便保存和读取JavaScript对象,同时还支持查询及搜索
    //IndexedDB操作完全是异步的,大多数操作会以请求进行,但这些操作会在后期执行,如果成功则返回数据,失败则返回错误。
    //差不多每次IndexedDB操作都需要注册onerror和onsuccess事件处理程序,以确保适当地处理结果

//1.数据库indexedDB本质是一个数据库 和传统数据库不同在于使用对象保存数据,而不是使用表来保存数据。
    //一个indexedDB数据库,就是一组位于相同命名空间下的对象的集合

var indexedDB = window.indexedDB || window.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB;
    function closeDB( db ) {
        db.close();
    }
    function deleteDB( name ) {
        debugger;
        indexedDB.deleteDatabase( name );
    }

function openDB( myDB, successHandler, upGradeHandler ) {
        var version = myDB.version || 1,
                request = indexedDB.open( myDB.name, version );

request.onerror = function ( e ) {
            console.log( e.currentTarget.error.message );
        };
        request.onsuccess = function ( e ) {
            myDB.db = e.target.result;
            successHandler && successHandler();
        };
        request.onupgradeneeded = function ( e ) { //请求数据库版本变化句柄
            console.log( ‘DB version changed to ‘ + version );
            myDB.db = e.target.result;
            upGradeHandler && upGradeHandler();
        };
    }
    function addData( db, storeName, addData ) {
        var transaction = db.transaction( storeName, ‘readwrite‘ ),//打开一个事务,参数一可以为字符串或者数组, 参数二为访问数据的方式readony readwrite
                store = transaction.objectStore( storeName );

for ( var i = 0; i < addData.length; i++ ) {
            store.add( addData[i] );
        }
    }
    function getDataByKey( db, storeName, value ) {
        var transaction = db.transaction( storeName, ‘readwrite‘ );
        var store = transaction.objectStore( storeName );
        var request = store.get( value );
        request.onsuccess = function ( e ) {
            var student = e.target.result;
            console.log( student.name );
        };
    }
    function updateDataByKey( db, storeName, value ) {
        var transaction = db.transaction( storeName, ‘readwrite‘ );
        var store = transaction.objectStore( storeName );
        var request = store.get( value );
        request.onsuccess = function ( e ) {
            var student = e.target.result;
            student.age = 35;
            store.put( student );
        };
    }
    function deleteDataByKey( db, storeName, value ) {
        var transaction = db.transaction( storeName, ‘readwrite‘ );
        var store = transaction.objectStore( storeName );
        store.delete( value );
    }
    function clearObjectStore( db, storeName ) {
        var transaction = db.transaction( storeName, ‘readwrite‘ );
        var store = transaction.objectStore( storeName );
        store.clear();
    }
    function deleteStore( db, storeName ) {
        db.objectStoreNames.contains( storeName ) && db.deleteObjectStore( storeName );
    }
    //索引是唯一的没问题,如果索引不唯一也只会取到第一个匹配值,要想得到所有符合条件的值就需要使用游标了
    function getDataByIndex( db, storeName, index ) {
        var transaction = db.transaction( storeName );
        var store = transaction.objectStore( storeName );
        var index = store.index( "nameIndex" );
        index.get( index ).onsuccess = function ( e ) {
            var student = e.target.result;
            console.log( student.id );
        }
    }

//游标 cursor有属性direction key value primaryKey 方法update() delete() continue() advance()
    // cursor.continue(key)如果指定了key会移动打指定key值处 没有则会使游标下移直到没有数据返回undefined。cursor.advance(count)向前移动多少
    function fetchStoreByCursor( db, storeName ) {
        var transaction = db.transaction( storeName );
        var store = transaction.objectStore( storeName );
        var request = store.openCursor();
        request.onsuccess = function ( e ) {
            var cursor = e.target.result;
            if ( cursor ) {
                console.log( cursor.key );
                var currentStudent = cursor.value;
                console.log( currentStudent.name );
                cursor.continue();
            }
        };
    }
    //游标+索引
    function getMultipleData( db, storeName ) {
        var transaction = db.transaction( storeName );
        var store = transaction.objectStore( storeName );
        var index = store.index( "ageIndex" );
        var IDBKeyRange=window.IDBKeyRange||window.webkitIDBKeyRange;
        var request = index.openCursor( IDBKeyRange.only( 26 ));
//        index.openCursor()/index.openKeyCursor()方法在不传递参数的时候会获取object store所有记录,像上面例子一样我们可以对搜索进行筛选
//        可以使用key range 限制游标中值的范围,把它作为第一个参数传给 openCursor() 或是 openKeyCursor()
//         第二个可选参数表示游标方向默认是向后
// 有:IDBCursor.NEXT向后 IDBCursor.NEXT_NO_DUPLICATE跳过重复向后 IDBCursor.PREV向前 IDBCursor.PREV_NO_DUPLICATE跳过重复向前
//        IDBKeyRange.only(value):只获取指定数据
//        IDBKeyRange.lowerBound(value,isOpen):获取最小是value的数据,第二个参数用来指示是否排除value值本身,也就是数学中的是否是开区间
//        IDBKeyRange.upperBound(value,isOpen):和上面类似,用于获取最大值是value的数据
//        IDBKeyRange.bound(value1,value2,isOpen1,isOpen2):不用解释了吧
        request.onsuccess = function ( e ) {
            var cursor = e.target.result;
            if ( cursor ) {
                var student = cursor.value;
                console.log( student.id );
                cursor.continue();
            }
        }
    }
    function getMultipleData( db, storeName ) {
        var transaction = db.transaction( storeName );
        var store = transaction.objectStore( storeName );
        var index = store.index( "nameIndex" );
        var request = index.openCursor( IDBKeyRange.bound( ‘B‘, ‘F‘, false,
                true
        ) );
        request.onsuccess = function ( e ) {
            var cursor = e.target.result;
            if ( cursor ) {
                var student = cursor.value;
                console.log( student.name );
                cursor.continue();
            }
        }
    }
    var myDB = {
        name : "zodiac",
        version : 1,
        db : null
    };

function successHandler() {

//在对新数据库做任何事情之前,需要开始一个事务。事务中需要指定该事务跨越哪些object store。

var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction,

transaction = myDB.db.transaction( [‘students‘, ‘teacher‘], "readonly" ),

objectStore = transaction.objectStore( ‘students‘ ); //获取students object store  objectStore相当于表

//开启事务后插入数据
        addData( myDB.db, ‘students‘, students );
        addData( myDB.db, ‘teacher‘, teacher );
    }

function upGradeHandler() {//跟新数据库 建表 必须在数据库版本变化后才能执行
        if ( !myDB.db.objectStoreNames.contains( ‘students‘ ) ) {
            var store = myDB.db.createObjectStore( ‘students‘, {keyPath : "id", autoIncrement : true} ); //keyPath主键 keyGenerator其他参数 autoIncrement默认为true
            store.createIndex( ‘ageIndex‘, ‘age‘, {unique : false} ); //创建索引 索引名称 索引属性字段名 索引属性值是否唯一
            store.createIndex( ‘nameIndex‘, ‘name‘, {unique : true} );
        }
        if ( !myDB.db.objectStoreNames.contains( ‘teacher‘ ) ) {
            myDB.db.createObjectStore( ‘teacher‘, {keyPath : "id", autoIncrement : true} );
        }
    }

var students = [
        {
            id : 1001,
            name : "Byron",
            age : 24
        },
        {
            id : 1002,
            name : "Frank",
            age : 30
        },
        {
            id : 1003,
            name : "Aaron",
            age : 26
        }
    ];
    var teacher = [
        {
            id : 1,
            name : "aa",
            age : 44
        },
        {
            id : 2,
            name : "bb",
            age : 45
        },
        {
            id : 3,
            name : "cc",
            age : 46
        }
    ];

openDB( myDB, null, upGradeHandler );
    openDB( myDB, successHandler );

// deleteDB("zodiac");
    //endregion

时间: 2024-11-02 10:31:46

离线应用和客户端存储的相关文章

Javascript高级程序设计-23:HTML5离线应用和客户端存储

一.离线检测 开发离线应用的第一个步骤是确定设备是在线还是离线,为此HTML5设置了一个navigator.onLine属性来表明浏览器是否可以上网.这个属性为true表示设备可以上网,值为false表示设备离线. if(navigator.online){ //online } else{ //offline } 除了navigator.online属性外,HTML5还专门设置了两个事件:online和offline,分别在设备上线和离线的时候触发. window.addEventListen

JS中离线应用与客户端存储

1.离线检测:H5定义了navigator.online属性,为true 表示设备能上网 还定义了两个相关事件:online和offline 2 数据存储 cookie--HTTP coolie,客户端存储会话信息的.该标准要求服务器对任意的HTTP请求发送Set-Cookie HTTP头作为响应的一部分' /* HTTP/1.1 200 OK Content-type: text/html Set-Cookie: name=value;expire=expiration_time;path=d

JavaScript中离线应用和客户端存储(cookies、sessionStorage、localStorage)

一.离线应用 所谓离线web应用,就是在设备不能上网的情况下仍然可以运行的应用. 开发离线web应用需要几个步骤:首先,确保应用知道设备是否能上网,以便下一步执行正确的操作:然后,应用还必须能访问一定的资源(图像.JavaScript.css等),只有这样才能正常工作:最后,必须有一块本地空间用于保存数据,无论能否上网都不妨碍读写. 1.离线检测 HTML5定义一个navigator.onLine属性,这个属性值为true表示设备能上网,值为false表示设备离线. 除了navigator.on

Web - 客户端存储的几种方式

客户端存储主要方便一些APP离线使用.今天就来说说客户端存储的方法有多少? 说在最前面的一句:所有的客户端存储都有一个原则:读写的数据必须要同域 1 Cookie Cookie是一项很老的技术的,就是因为它老,所以兼容性还是不错的.常见的JS操作Cookie的代码如下: function setCookie(c_name,value,expiredays) { var exdate=new Date() exdate.setDate(exdate.getDate()+expiredays) do

第十八章:客户端存储

写在本章开始前: 第十七章作为独立的一章,涉及到jQuery的方方面面,是篇幅很长的一章.为了更新客户端存储(本章),特跳过十七章.(十七章将在本章完成后继续更新,望大家关注.) web应用允许使用浏览器提供的API实现将数据存储在用户电脑上.这种客户端存储相当于赋予了web浏览器记忆功能.比方说,web应用就可以用这些方式来“记住”用户的偏好甚至是用户的所有状态信息,以便准确地“回忆”起用户上一次访问的位置.客户端存储遵循“同源策略”,因此不同站点的页面是无法读取对于存储的数据.而同一站点的不

JavaScript权威指南第20章 客户端存储

20 客户端存储 客户端存储的几种形式: web存储 cookie IE userData 离线应用 web数据库 文件系统api 20.1 localStorage 和 sessionStorage 20.1 .1 存储有效期和作用域 localStorage 和 sessionStorage区别在于存储的有效期和作用域不同. localStorage的作用域限制在文档源级别的. 文档源:协议 主机名 端口 决定同一个文档源 同源的文档源可以共享同一个localStorage,甚至可以修改和覆

客户端存储之HTML5 web存储

最近在学习如何实现客户端存储,这篇文章将主要分析H5的web storage以及它与传统的cookie之间的区别. web存储与cookie的区别以及优势: 1.cookie只适合存储少量文本数据,而web存储可存储大量数据 2.以cookie存储的数据,无论服务器端是否需要,每次HTTP请求时,都会将cookie数据传送到服务端,有时会造成带宽浪费,而web storage 中的数据只会存储在本地 3.web storage有更加丰富易用的接口,比如setItem().getItem().re

【Java编码准则】の #02不要在客户端存储未加密的敏感信息

当构建CS模式的应用程序时,在客户端侧存储敏感信息(例如用户私要信息)可能导致非授权的信息泄漏. 对于Web应用程序来说,最常见的泄漏问题是在客户端使用cookies存放服务器端获取的敏感信息.Cookies是由web服务器创建的,它具有一个指定的有效时间,保存在客户端.当客户端连接上服务器端时,客户端使用cookies中存储的信息向服务器端进行认证,通过后服务器端返回敏感信息. 在XSS攻击下,Cookies不能保证敏感信息的安全.无论是通过XSS攻击,还是直接对客户端的攻击,攻击者一旦获取到

HTML5学习笔记之客户端存储数据方法:localStorage(),sessionStorage()

HTML5提供了两种在客户端存储数据的新方法: localStorage():没有时间限制的数据存储 sessionStorage():针对一个session的数据存储 下面的一个例子用localStroage()方法对用户访问页面的次数进行计数 <script type="text/javascript"> if(localStorage.pagecount) { localStorage.pagecount=Number(localStorage.pagecount)+