html5 IndexedDB

来源:互联网 发布:2017网络最新最火的词 编辑:程序博客网 时间:2024/05/22 03:04

indexedDB类似nosql的数据库,是面向索引的数据库,相对于web storage,它为web离线存储提供大数据存储和搜索。

浏览器兼容性

这里写图片描述

使用步骤

  1. 打开一个数据库
  2. 获取数据库对象
  3. 通过数据库打开一个事务
  4. 通过事务进行数据库结构和数据的操作

操作数据之前,我们先建立一个数据库

/**  * 创建数据库  */function createDB(){  var openReq = window.indexedDB.open(dbName);  openReq.onerror = function(ev){  };  openReq.onsuccess = function(ev){      var db = ev.target.result ;      tip.innerText = "数据库名称 : " + db.name;  };}

由于indexedDB数据库兼容性还不是很好,需要为各自的对象各自浏览器加上前缀,我们 可以按下面来做统一对象

window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;//indexDB对象window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction || {READ_WRITE: "readwrite"}; // 事务对象window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange; //key过滤对象

创建的同时,我也要能删除数据库,我们可以这样子删除数据库

/**  * 删除数据库  */function delDB(){   var openReq = window.indexedDB.deleteDatabase(dbName);   openReq.onerror = function(ev){   };   openReq.onsuccess = function(ev){     tip.innerText = "删除数据库成功";   };}

上面的操作设计到如下方法和事件

  1. window.indexedDB 获取数据库对象
  2. open(dbName,version) 打开数据,是操作整个数据库的入口,第二个参数是version(long 型),它的作用对数据库进行版本控制,若要对数据库的接口和数据进行操作,必须让version版本号大于之前操作的版本号数

indexedDB的数据库打开是异步操作,需要回调事件才确定打开接口,提供一下事件

  1. onerror 数据库打开失败的触发
  2. onsuccess 数据库打开成功触发
  3. onupgradeneeded version版本号和上一次操作版本号不一致触发,我们可以在里面对数据库进行数据结构和数据库进行操作,我们每次操作数据库的增删改查,都要确定version号比上次操作大,才能触发onupgradeneeded 进行数据库操作

三个事件都传事件对象到方法里面,可以通过事件对象获取数据库对象或者结果集,事务对象等等

创建好了数据库之后,我们就来创建一个存储对象,你可以理解为关系数据库中的表,那下面我建一个消费者customers的表

/**  *创建一个存储对象  */function createObjectStore(){    var openReq = window.indexedDB.open(dbName,4); //只有改变版本号才能对该数据库结构和数据进行操作    openReq.onsuccess = function(ev){     tip.innerText = "创建存储对象成功";   };   openReq.onerror = function(ev){     tip.innerText = "失败";   };   openReq.onupgradeneeded = function(ev){//版本号不同调发这个回调      var db = ev.target.result ; //获取数据库对象      //创建表名和主键      var objectStore = db.createObjectStore("customers", { autoIncrement : true}); //创建存储对象,利用autoIncrement主键自动递增      //创建字段索引,索引可以用来搜索,详细看后面      objectStore.createIndex("uid","uid",{unique : true});      objectStore.createIndex("age","age",{unique : false});      objectStore.createIndex("name", "name", { unique: false });   };}

该创建步骤设计到以下方法

  1. createObjectStore(dbName,primaryKey) 创建一个存储对象
  2. createIndex(colunmName,indexName,option) 创建一个字段索引

创建primaryKey的时候有俩种方式

  1. 自动递增的主键策略,如{ autoIncrement : true},
  2. 拿索引字段中的一个不重复的索引作为主键的策略,如{ keyPath: “uid” }

俩种的区别,是在更新的时候,”1”的策略,不会更新数据,而是直接向数据库重新插入一条数据,因为主键key每次都是递增不相同。”2”的策略会直接更新数据

createIndex不需要为每个字段建立索引,只需建立你需要的索引就可以了,例如我们把下面的数据类型插到数据库中

const customerData = [ //数据类型json,可以把key理解为字段,建立索引的时候,没必要为每个字段建立索引  { uid: "aaa", name: "根子", age: 15, email: "genzi@qq.com" },  { uid: "bbb", name: "花子", age: 11, email: "mingzi@qq.com" }];/**  * 添加一条数据  */function addData(){   var req = window.indexedDB.open(dbName,15);   req.onupgradeneeded = function(ev){      var db = ev.target.result ;      var transaction = ev.target.transaction || db.transaction(["customers"],IDBTransaction.READ_WRITE); //获取事务      transaction.oncomplete = function(ev){        tip.innerText = "添加数据成功";      };      transaction.onerror = function(ev){      };      var objectStore = transaction.objectStore("customers");//获取事务型的存储对象      for(var i in customerData){         objectStore.add(customerData[i]);      }   } }

就像关系行数据库一样,在索引数据库中,我们也必须要加上事务控制,避免数据操作不一致。一般读数据,用IDBTransaction.READ,而写数据,我们用IDBTransaction.READ_WRITE关键字来标志

下面我们把更新和删除也举例一下

/**  * 更新一条数据  */function updateData(key,name,age,email){   var req = window.indexedDB.open(dbName,++index);   req.onupgradeneeded = function(ev){      var db = ev.target.result;      var transaction = ev.target.transaction || db.transaction(["customers"],IDBTransaction.READ_WRITE);      var objstore = transaction.objectStore("customers");      var getReq = objstore.get(key); //通过主键直接获取一个对象      transaction.oncomplete = function(ev){         tip.innerText = "更新数据成功";      };      transaction.onerror = function(ev){      };      getReq.onsuccess = function(){ //获取数据成功         var obj = getReq.result; //获取数据对象         obj.ssn = "343tt4343" ;          obj.name = name ;          obj.age = age ;          obj.email = email ;          objstore.put(obj);//更新数据,主键策略不同,更新结果也会不同      }   };}/**  * 删除一条数据  */function delData(){  var req = window.indexedDB.open(dbName,++index);  req.onupgradeneeded = function(ev){      var db = ev.target.result;      var transaction = ev.target.transaction || db.transaction(["customers"],IDBTransaction.READ_WRITE);      var objstore = transaction.objectStore("customers");      transaction.oncomplete = function(ev){         tip.innerText = "删除数据成功";      };      transaction.onerror = function(ev){      };      objstore.delete(1);   }}

任何对数据库的增删改查,都需要加上事务获取事务型的存储对象,可以理解为关系型数据库中的表,先找表,再对表进行CRUD,下面来看看查询操作。

get 通过primary key来获取数据对象

/**  * 更新一条数据  */function findDataByKey(key){   var req = window.indexedDB.open(dbName,++index);   req.onupgradeneeded = function(ev){      var db = ev.target.result;      var transaction = ev.target.transaction || db.transaction(["customers"],IDBTransaction.READ_WRITE);      var objstore = transaction.objectStore("customers");      var getReq = objstore.get(key); //通过主键直接获取一个对象         getReq.onsuccess = function(){ //获取数据成功         var obj = getReq.result; //获取数据对象,auto         ...      }   };}

openCursor 打开游标来遍历数据

/**  * 遍历获取全部数据  */function retriving(){   //1.打开数据库   var req = window.indexedDB.open(dbName,++index);   //2.判断成功,打开事务   req.onupgradeneeded = function(ev){       var db = ev.target.result; //获取数据库对象       var transaction = ev.target.transaction || db.transaction(["customers"],IDBTransaction.READ); //打开事务       var objstore = transaction.objectStore("customers");//获取操作存储对象       var cursor = objstore.openCursor(); //打开游标       cursor.onsuccess = function(ev){          var result = ev.target.result ;          if (result) {            console.log("key = " + result.key + " -- name = " + result.value.name);            result.continue(); //继续遍历          }          else {            tip.innerText = "遍历完成";          }       }       }}

index 通过索引来获取对象

/**  * 用index获取数据  */function findByIndex(index){   var req = window.indexedDB.open(dbName,++index);   req.onupgradeneeded = function(ev){       var transaction = ev.target.transaction || db.transaction(["customers"],IDBTransaction.READ); //打开事务       var objstore = transaction.objectStore("customers");//获取操作存储对象       var item = objstore.index("name"); //通过建立的name索引来获取对象       item.get("lucy").onsuccess = function(event) {//获取匹配的一条数据          tip.innerText = "lucy's SSN is " + event.target.result.ssn;      };   }}

通过index获取的数据可能不只一条数据,如果是多条数据,我们也可以继续用游标进行遍历

/**  * 用indexcursor来变量列  */function retrivingByIndexCusor(){   var req = window.indexedDB.open(dbName,++index);   req.onupgradeneeded = function(ev){       var transaction = ev.target.transaction || db.transaction(["customers"],IDBTransaction.READ); //打开事务       var objstore = transaction.objectStore("customers");//获取操作存储对象       var item = objstore.index("name");       item.openCursor().onsuccess = function(ev) {//打开 游标进行遍历          var cursor = ev.target.result;          if (cursor) {            console.log( cursor.key + ", uuid: " + cursor.value.uuid+ ", email: " + cursor.value.email);            cursor.continue();          }        };      }}

IDBKeyRange 用来做指定获取数据的范围,类型关系型数据中start limit处理分页的一样

/**  * 利用keyRange来获取指定范围的的数据  */function useIDBKeyRange(){   var req = window.indexedDB.open(dbName,18);   req.onupgradeneeded = function(ev){       var transaction = ev.target.transaction || db.transaction(["customers"],IDBTransaction.READ); //打开事务       var objstore = transaction.objectStore("customers");//获取操作存储对象       var item = objstore.index("age");       // 匹配唯一对象        //var singleKeyRange = IDBKeyRange.only(15);        // 匹配age大于15的那些对象,包括age=15那个对象        //var lowerBoundKeyRange = IDBKeyRange.lowerBound(15);        // 匹配age大于15的那些对象,不包括age=15那个对象        //var lower BoundOpenKeyRange = IDBKeyRange.lowerBound("Bill", true);        // 匹配age小于15的那些对象,不包括age=15那个对象        var upperBoundOpenKeyRange = IDBKeyRange.upperBound(15);        //匹配age在15和50中间的对象,不报错15但报错50         //var boundKeyRange = IDBKeyRange.bound(15, 50, false, true);         item.openCursor(upperBoundOpenKeyRange).onsuccess = function(ev) {          var cursor = ev.target.result;          if (cursor) {            console.log( cursor.key + ", SSN: " + cursor.value.ssn + ", email: " + cursor.value.email);            cursor.continue();          }        };     }}

我们还可以通过”prev”来进行排序

item.openCursor(upperBoundOpenKeyRange,"prev").onsuccess = function(ev) { //默认排序从小到大,prev能从大到小          var cursor = ev.target.result;          if (cursor) {            console.log( cursor.key + ", SSN: " + cursor.value.ssn + ", email: " + cursor.value.email);            cursor.continue();          }        }; 

当有age获取数据有重复的时候,例如35岁的有很多个,我们可以通过”nextunique”获取唯一的一条数据

item.openCursor(upperBoundOpenKeyRange,"nextunique").onsuccess = function(ev) { //默认排序从小到大,prev能从大到小          var cursor = ev.target.result;          if (cursor) {            console.log( cursor.key + ", SSN: " + cursor.value.ssn + ", email: " + cursor.value.email);            cursor.continue();          }        }; 

博客参考
https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB

0 0
原创粉丝点击