首頁  >  文章  >  web前端  >  將資料庫從伺服器移到瀏覽器--indexedDB基本操作封裝

將資料庫從伺服器移到瀏覽器--indexedDB基本操作封裝

巴扎黑
巴扎黑原創
2017-06-23 14:04:451871瀏覽

  資料庫是屬於伺服器的,這是天經地義的事,但是有時候資料也許並非需要儲存在伺服器,但是這些資料也是一條一條的記錄,怎麼辦?今天來帶領你來領略H5的一個新特性--indexedDB的風騷。你會情不自禁的發出感嘆--不可思議!

一、連結資料庫

  indexedDB沒有建立資料庫的概念,你可以直接連結資料庫,如果你連結的資料庫不存在,那麼會自動的建立一個資料庫。看下面的這個例子。

  

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title></head><body><button type="" id=&#39;conbtn&#39;>链接数据库</button><script>// In the following line, you should include the prefixes of implementations you want to test.    window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;   // DON'T use "var indexedDB = ..." if you're not in a function.
   // Moreover, you may need references to some window.IDB* objects:   window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
   window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange   // (Mozilla has never prefixed these objects, so we don't need window.mozIDB*)
   function connectDB(name,version,success,error){
         let dbConnect = indexedDB.open(name,version);
              dbConnect.onsuccess = function(e){
                  console.log('数据库链接成功!');
                success(e.target.result);            
            }
            dbConnect.onerror = function(e){
                console.log('数据库链接失败!');
                error(e);
            }
            dbConnect.onupgradeneeded = function(e){
                success(e.target.result);
                let oldVersion = e.oldVersion;
                let newVersion = e.newVersion;
                console.log('数据库更新成功,旧的版本号为:'+oldVersion+",新的版本号为:"+newVersion);
            }
   }
   window.onload=function(){
           let btn  = document.getElementById('conbtn');
           btn.onclick = function(){
               connectDB('haha',1,function(){
                   console.log('链接成功,或者更新成功回调函数');
               },function(){
                   console.log('链接失败回调函数!')
               });
           }
   }</script></body></html>

  我點了兩次連結資料庫,結果是這樣的。

 

  在Application的indexedDB中我們發現多了一個東西。

  

  可以看到haha資料庫已經成功建立了。

  indexedDB的open方法用來連結或更新資料庫,第一次建立也認為是一次更新。第一個參數是資料庫的名字,第二個參數為版本號。第一次建立或版本號改變時出發更新事件upgradeneeded,連結成功後出發success事件,連結出錯時觸發error事件。

二、建表和索引

  

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title></head><body><button type="" id=&#39;conbtn&#39;>链接数据库</button><script>// In the following line, you should include the prefixes of implementations you want to test.    window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;   // DON'T use "var indexedDB = ..." if you're not in a function.
   // Moreover, you may need references to some window.IDB* objects:   window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
   window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange   // (Mozilla has never prefixed these objects, so we don't need window.mozIDB*)
   function connectDB(name,version,success,update,error){
         let dbConnect = indexedDB.open(name,version);
              dbConnect.onsuccess = function(e){
                  console.log('数据库链接成功!');
                success(e.target.result);            
            }
            dbConnect.onerror = function(e){
                console.log('数据库链接失败!');
                error(e);
            }
            dbConnect.onupgradeneeded = function(e){
                update(e.target.result);
                let oldVersion = e.oldVersion;
                let newVersion = e.newVersion;
                console.log('数据库更新成功,旧的版本号为:'+oldVersion+",新的版本号为:"+newVersion);
            }
   }       function createTable(idb,storeName,key,idxs){if(!idb){
            console.log(idb);return ;
        }if(!key || !idxs){
            console.log('参数错误');return ;
        }if(!storeName){
            console.log('storeName必须');return ;
        }try{var store = idb.createObjectStore(storeName,key);
            console.log('数据库存储对象(table)创建成功');for(var i = 0;i<idxs.length;i++){var idx = idxs[i];
                store.createIndex(idx.indexName,idx.keyPath,idx.optionalParameters);
                    console.log('索引'+idx.indexName+'创建成功');
            }
        }catch(e){
            console.log('建表出现错误');
            console.log(JSON.stringify(e))
        }
    }
   window.onload=function(){
           let btn  = document.getElementById('conbtn');
           btn.onclick = function(){
               connectDB('haha',1,                 function(idb){
                   console.log('链接成功,或者更新成功回调函数');
               },function(idb){                   createTable(idb,'test',{keyPath:'id',autoIncrement:true},[
                       {
                       indexName:'testIndex',
                     keyPath:'name',
                     optionalParameters:{
                         unique:true,
                         multiEntry:false }}]);                   
               },function(){
                   console.log('链接失败回调函数!')
               });
           }
   }</script></body></html>

 

  我點了一下按鈕結果時這樣的。

  

  

  這裡用到的兩個核心方法時createObjectStore,和createIndex,這兩個方法必須在資料庫發生更新的事件中執行。

  createObjectStore方法可以理解成是創建表,接受第一個參數為一個字串,表示表名,第二個參數是一個對象,指定主鍵相關的東西,{keyPath:'主鍵是哪個字段',autoIncrement:是否自增}。

  createIndex方法是建立索引的,接受三個參數,第一個是字串,表示索引的名字,第二個參數表示欄位名稱(誰的索引),第三個參數是個對象,具體自己查去。索引的作用是在查詢操作時可以用到,不詳講,自行google吧。

三、新增資料

  

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title></head><body><button type="" id=&#39;conbtn&#39;>链接数据库</button><button type="" id=&#39;add&#39;>添加数据</button><script>// In the following line, you should include the prefixes of implementations you want to test.    window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;   // DON'T use "var indexedDB = ..." if you're not in a function.
   // Moreover, you may need references to some window.IDB* objects:   window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
   window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange   // (Mozilla has never prefixed these objects, so we don't need window.mozIDB*)
   function connectDB(name,version,success,update,error){
         let dbConnect = indexedDB.open(name,version);
              dbConnect.onsuccess = function(e){
                  console.log('数据库链接成功!');
                success(e.target.result);            
            }
            dbConnect.onerror = function(e){
                console.log('数据库链接失败!');
                error(e);
            }
            dbConnect.onupgradeneeded = function(e){
                update(e.target.result);
                let oldVersion = e.oldVersion;
                let newVersion = e.newVersion;
                console.log('数据库更新成功,旧的版本号为:'+oldVersion+",新的版本号为:"+newVersion);
            }
   }       function createTable(idb,storeName,key,idxs){if(!idb){
            console.log(idb);return ;
        }if(!key || !idxs){
            console.log('参数错误');return ;
        }if(!storeName){
            console.log('storeName必须');return ;
        }try{var store = idb.createObjectStore(storeName,key);
            console.log('数据库存储对象(table)创建成功');for(var i = 0;i<idxs.length;i++){var idx = idxs[i];
                store.createIndex(idx.indexName,idx.keyPath,idx.optionalParameters);
                    console.log('索引'+idx.indexName+'创建成功');
            }
        }catch(e){
            console.log('建表出现错误');
            console.log(JSON.stringify(e))
        }
    }function add(storeName,values){
    connectDB('haha',1,function(idb){var ts = idb.transaction(storeName,"readwrite");var store = ts.objectStore(storeName);        for(var i = 0;i<values.length;i++){
            (function(i){var value = values[i];var req = store.put(value);
                req.onsuccess = function(){
                    console.log("添加第"+i+"个数据成功");
                }
                req.onerror = function(e){
                    console.log("添加第"+i+"个数据失败");
                    console.log(JSON.stringify(e));
                }                            
            })(i)

        }
        ts.oncomplete = function(){
            console.log('添加数据事务结束!');
        }
    },function(){},function(){});

                
    }
   window.onload=function(){
           let btn  = document.getElementById('conbtn');
           btn.onclick = function(){
               connectDB('haha',1,                 function(idb){
                   console.log('链接成功,或者更新成功回调函数');
               },function(idb){
                   createTable(idb,'test',{keyPath:'id',autoIncrement:true},[
                       {
                       indexName:'testIndex',
                     keyPath:'name',
                     optionalParameters:{
                         unique:true,
                         multiEntry:false }}]);                   
               },function(){
                   console.log('链接失败回调函数!')
               });
           }
           let add1 = document.getElementById('add');
           add1.onclick = function(){
               add('test',[{name:"fjidfji",a:'uuuu'}])
           }
   }</script></body></html>

 

 

  比較神奇的是你在建表的時候不需要指定你的字段,再添加數據時可以隨便加。增加資料用到的是表物件的put方法,之前需要一個事務,從事務調個方法拿到儲存物件(可以理解為表),具體看看範例就明白了。

四、查詢資料

Document链接数据库添加数据查询

 

#   查詢操作主要用到了遊標,這個說起來還比較多,沒時間說了,自行google。還有很多的操作這裡不講了。給一個我封裝的不是很好的簡易庫,僅供參考。

   

一個簡易函式庫。

###
(function(window){'use strict';
    window.dbUtil={
    indexedDB :(window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB),

    IDBTransaction :(window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction),

    IDBKeyRange :(window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange),

    IDBCursor : (window.IDBCursor || window.webkitIDBCursor || window.msIDBCursor),            
    idb:null,
    dbName:"",
    dbVersion:"",/**
     * 初始化数据库,创建表和建立链接
     * @param  {[type]} dbName    [description]
     * @param  {[type]} dbVersion [description]
     * @param  {[type]} storeObjs [description]
     * @return {[type]}           [description]     */initDB:function (dbName,dbVersion,storeObjs){this.dbName = dbName;this.dbVersion = dbVersion;var dbConnect = this.indexedDB.open(this.dbName,this.dbVersion);var self = this;
        dbConnect.onsuccess = function(e){
            self.idb = e.target.result;
            self.log('数据库链接成功!');                
        }
        dbConnect.onerror = function(e){
            console.log(e)
            self.log('数据库链接失败!');
        }
        dbConnect.onupgradeneeded = function(e){
            self.idb = e.target.result;var ts = e.target.transaction;var oldVersion = e.oldVersion;var newVersion = e.newVersion;
            self.log('数据库更新成功,旧的版本号为:'+oldVersion+",新的版本号为:"+newVersion);if(storeObjs){for(var k = 0,len=storeObjs.length;k<len;k++){var storeObj = storeObjs[k];var storeName = storeObj.storeName;var key = storeObj.key;var idxs = storeObj.idxs;

                    self.createTable(storeName,key,idxs)
                }
            }
        }
    },/**
     * 创建数据库存储对象(表)
     * @param  {[type]} key [description]
     * @param  {[type]}     [description]
     * @return {[type]}     [description]     */createTable:function(storeName,key,idxs){var self = this;var idb = self.idb;if(!idb){
            self.log('数据库没有链接');return ;
        }if(!key || !idxs){
            self.log('参数错误');return ;
        }if(!storeName){
            self.log('storeName必须');return ;
        }try{var store = idb.createObjectStore(storeName,key);
            self.log('数据库存储对象(table)创建成功');for(var i = 0;i<idxs.length;i++){var idx = idxs[i];
                store.createIndex(idx.indexName,idx.keyPath,idx.optionalParameters);
            self.log('索引'+idx.indexName+'创建成功');
            }
        }catch(e){
            self.log('建表出现错误');
            console.log(JSON.stringify(e))
        }
    },/**
     * [add description]
     * @param {[type]} storeName [description]
     * @param {[type]} values    [description]     */add:function(storeName,values){var dbConnect = this.indexedDB.open(this.dbName,this.dbVersion);var self = this;
        dbConnect.onsuccess = function(e){var idb = e.target.result;var ts = idb.transaction(storeName,"readwrite");var store = ts.objectStore(storeName);for(var i = 0;i<values.length;i++){
                (function(i){var value = values[i];var req = store.put(value);
                    req.onsuccess = function(){
                        self.log("添加第"+i+"个数据成功");
                    }
                    req.onerror = function(e){
                        self.log("添加第"+i+"个数据失败");
                        self.log(JSON.stringify(e));
                    }                            
                })(i)

            }
            ts.oncomplete = function(){
                self.log('添加数据事务结束!');
            }
                    
        }

    },/**
     * [select description]
     * @param  {[type]}   storeName [description]
     * @param  {[type]}   count     [description]
     * @param  {Function} callback  [description]
     * @param  {[type]}   indexName [description]
     * @return {[type]}             [description]     */select:function(storeName,count,callback,indexName){var dbConnect = this.indexedDB.open(this.dbName,this.dbVersion);var self = this;var total = 0;var data = [];
        dbConnect.onsuccess = function(e){
            self.log("数据库链接成功!");var idb = e.target.result;var ts = idb.transaction(storeName,"readonly");var store = ts.objectStore(storeName);var req = store.count();var req2 = null;
            req.onsuccess = function(){
                total = this.result;var realCount = (count<=total)?count:total;if(typeof indexName == 'undefined'){var range = IDBKeyRange.bound(0,"9999999999999999999999");
                    req2 = store.openCursor(range,'prev');var cc = 0;
                    req2.onsuccess = function(){var cursor = this.result;if(total == 0){
                            callback([]);return;
                        }if(cursor){                        
                            cc++;
                            data.push(cursor.value);if(cc==realCount){
                                callback(data);return;
                            }
                            cursor.continue();
                        }
                    }
                    req2.onerror = function(){
                        self.log("检索出错")
                    }
                }else{//待写                }                        
            }

        }
    },/**
     * [delete description]
     * @param  {[type]} storeName [description]
     * @param  {[type]} key       [description]
     * @return {[type]}           [description]     */delete:function(storeName,key,callback){var dbConnect = this.indexedDB.open(this.dbName,this.dbVersion);
        let self = this;
        dbConnect.onsuccess = function(e){var idb = e.target.result;var ts = idb.transaction(storeName,'readwrite');var store = ts.objectStore(storeName);
            store.delete(key);
            self.log('删除成功!');if(callback){
                callback();
            }
        }
    },/**
     * [funciton description]
     * @param  {[type]} storeName    [description]
     * @param  {[type]} key          [description]
     * @param  {[type]} existCall    [description]
     * @param  {[type]} notExistCall [description]
     * @return {[type]}              [description]     */isExist:function(storeName,key,existCall,notExistCall){var dbConnect = this.indexedDB.open(this.dbName,this.dbVersion);
        dbConnect.onsuccess = function(e){var idb = e.target.result;var ts = idb.transaction(storeName,'readonly');var store = ts.objectStore(storeName);var req = store.get(key);
            req.onsuccess = function(){if(this.result == undefined){
                    notExistCall();
                }else{
                    existCall(this.result);
                }
            }
            req.onerror = function(){
                notExistCall();
            }
        }
    },/**
     * clear
     * @param  {[type]} storeName [description]
     * @return {[type]}           [description]     */clear:function clearObjectStore(storeName){var dbConnect = this.indexedDB.open(this.dbName,this.dbVersion);
            dbConnect.onsuccess = function(e){var idb = e.target.result;var ts = idb.transaction(storeName,'readwrite');var store = ts.objectStore(storeName);
                store.clear();
            }        
    },/**
     * 删除数据库
     * @param  {[type]} dbName [description]
     * @return {[type]}        [description]     */dropDatabase:function(dbName){this.indexedDB.deleteDatabase(dbName);this.log('成功删除数据库:'+dbName);
    },/**
     * [log description]
     * @param  {[type]} msg [description]
     * @return {[type]}     [description]     */log:function(msg){
        console.log((new Date()).toTimeString()+":"+msg)
    }

    }

})(window);
###### ######五、使用indexedDB的優缺點######  1、優點:可以將一些資料放到瀏覽器端,不用和伺服器互動就可以實現一些功能,減輕伺服器負擔,加快回應速度。 ######  2、缺點:######  (1)不可靠:使用者可能刪處indexedDB,而且更換瀏覽器或裝置後這些資料就沒了。 ######  2)不方便於資料收集:有很多時候將資料存到伺服器是為了取得一些數據,如果放到瀏覽器端,這些資料比較難取得。 ###### (3)無法分享:不同使用者沒辦法分享數據,甚至時一個裝置的不同瀏覽器也沒辦法共用。 ######  所以,是否適用indexedDB要進行一下利弊權衡,不是有了indexedDB就啥也不管,一骨腦將資料放進去。 ######  ######  最近兩個課程設計,還有面試, 文章寫的比較匆忙,如有問題請各位園友批評指正。最近找實習,各位園友要是我寫的東西還可以而且公司招募實習生的話可以給大熊一個機會,謝謝! ###

以上是將資料庫從伺服器移到瀏覽器--indexedDB基本操作封裝的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn