数据库是属于服务器的,这是天经地义的事,但是有时候数据也许并非需要存储在服务器,但是这些数据也是一条一条的记录,怎么办?今天来带领你领略一下H5的一个新特性--indexedDB的风骚。你会情不自禁的发出感叹--不可思议!

一、链接数据库

  indexedDB没有创建数据库的概念,你可以直接链接数据库,如果你链接的数据库并不存在,那么会自动的创建一个数据库。看下面的这个例子。

  

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title> </head>
<body>
<button type="" id='conbtn'>链接数据库</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='conbtn'>链接数据库</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='conbtn'>链接数据库</button>
<button type="" id='add'>添加数据</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方法,之前需要一个事务,从事务调个方法拿到存储对象(可以理解为表),具体看看例子就明白了。

四、查询数据

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title> </head>
<body>
<button type="" id='conbtn'>链接数据库</button>
<button type="" id='add'>添加数据</button>
<button type="" id="selectBtn">查询</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(){}); }
function select(storeName,count,callback){
connectDB('haha',1,function(idb){
var total = 0;
var data = [];
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;
var range = IDBKeyRange.bound(0,Number.MAX_VALUE);
req2 = store.openCursor(range,'prev');
var cc = 0;
req2.onsuccess = function(){
var cursor = this.result;
if(cursor){
cc++;
data.push(cursor.value);
if(cc==realCount){
callback(data);
return;
}
cursor.continue();
}
}
req2.onerror = 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'}])
}
let selectBtn = document.getElementById('selectBtn');
selectBtn.onclick = function(){
select('test',2,function(data){
console.log(data);
})
}
}
</script>
</body>
</html>  

  查询操作主要用到了游标,这个说起来还比较多,没时间说了,自行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就啥也不管,一骨脑将数据放进去。

  

  最近两个课程设计,还有面试, 文章写的比较匆忙,如有问题请各位园友批评指正。最近找实习,各位园友要是我写的东西还可以而且公司招聘实习生的话可以给大熊一个机会,谢谢!

最新文章

  1. PHP安装mysql.so扩展
  2. 【Telnet】使用Telnet协议连接到远程Shell执行脚本
  3. CAShapeLayer
  4. Handling HTTP 404 Error in ASP.NET Web API
  5. (转)MySql可视化工具MySQL Workbench使用教程
  6. SQL2012数据库还原失败System.Data.SqlClient.SqlError: 无法执行 BACKUP LOG,因为当前没有数据库备份
  7. MVC从路由到Controller运行机制
  8. 共有和私有、name mangling
  9. 使用队列queue实现一个简单的生产者消费者模型
  10. iOS命名规范(转载)
  11. cmd copy命令 文件复制【转】
  12. WINDOWS 命令行 串口 COM 发送数据
  13. js闭包的使用
  14. hackerrank-knapsack
  15. spring boot 2.0 + 静态资源被拦截,怎么办?
  16. Mongo 后台加索引踩坑
  17. 【python】matplotlib中文乱码问题
  18. Memory stream is not expandable
  19. Qt自定义插件编程小结
  20. http之post方法 提交数据的四种方法

热门文章

  1. Linux之定时任务
  2. oracle job执行失败
  3. 超简单jQuary链式操作代码实现手风琴效果
  4. java图片上传(mvc)
  5. Brief introduction to Cassandra 【Cassandra简介】
  6. 如何使用Handler
  7. 如何在.Net中使用MongoDB
  8. 将非官方扩展程序加入chrome的白名单
  9. 使用babel编译es6
  10. Unity User Group 北京站:《Unity5.6新功能介绍以及HoloLens开发》