離線應用和客戶端存儲


    //region離線檢測
    //判斷設備是否能上網 navigator.onLine  window事件online offline
    //alert( navigator.onLine );html

    //監測網絡變化
    W.addHandler( window, "online", function () {
        alert( "online" );
    } );
    W.addHandler( window, "offline", function () {
        alert( "offline" );
    } );
    //endregionweb

 

    //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加密鏈接才能傳輸cookie

    //設置在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

相關文章
相關標籤/搜索