IndexedDB是一种低级API,用于客户端存储大量结构化数据(包括, 文件/blobs)。该API使用索引来实现对该数据的高性能搜索。虽然Web Storage 对于存储较少量的数据很有用,但对于存储更大量的结构化数据来说,这种方法不太有用。IndexedDB提供了一个解决方案。
关键概念
IndexedDB是一个事务型数据库系统
IndexedDB是一个基于JavaScript的面向对象的数据库
IndexedDB允许您存储和检索用键索引的对象
IndexedDB分别为同步和异步访问提供了单独的API,但是同步API还没有被任何浏览器所实现,既我们现在所使用的API都是异步的
存储空间限制
Firefox: 对IndexedDB数据库的大小没有限制。在用户界面上只会针对存储超过50 MB大小的BLOB(二进制大对象)请求权限。
Google Chrome: 参见https://developers.google.com/chrome...rage#temporary
用法
打开数据库
// 打开数据库时需要传数据库名和版本号,如果数据库不存在或版本号改变会先执行onupgradeneeded再执行onsuccess回调,可在onupgradeneeded回调里创建表等
var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB,
request = indexedDB.open(DBName, version);
request.onsuccess = function (e) {
var DB = e.target.result;
console.log('打开数据库成功,记录下数据库链接');
}
request.onerror = function (e) {
console.log('打开数据库失败:' + e.target.message);
}
request.onupgradeneeded = function (e) {
var DB = e.target.result;
// 判断表是否已经存在
if (!DB.objectStoreNames.contains(tableName)) {
// 创建表,keyPath设置表的索引字段,autoIncrement索引值是否自动递增生成数字
var objectStore = DB.createObjectStore(tableName, {
keyPath: 'id',
autoIncrement: true
});
// 指定其他可以被索引的字段(unique表示字段值是否唯一)
objectStore.createIndex('shopId', 'shopId', {
unique: false
});
}
}
关闭数据库链接
// DB为上面记录数据库链接的变量名
DB.close();
删除数据库
var delDB = window.indexedDB.deleteDatabase(DBName);
delDB.onsuccess = function () {
console.log('删除数据库成功');
}
delDB.onerror = function () {
console.log('删除数据库失败');
}
添加数据
var transaction = DB.transaction([tableName], 'readwrite'),
store = transaction.objectStore(tableName),
request = store.add(objData);
request.onsuccess = function (e) {
var key = e.target.result;
console.log('添加数据成功,新添加的数据key为:' + key);
}
request.onerror = function () {
console.log('添加数据失败');
}
删除数据
var transaction = DB.transaction([tableName], 'readwrite'),
store = transaction.objectStore(tableName),
request = store.delete(key);
request.onsuccess = function () {
console.log('删除数据成功');
}
request.onerror = function () {
console.log('删除数据失败');
}
修改数据
var transaction = DB.transaction([tableName], 'readwrite'),
store = transaction.objectStore(tableName),
request = store.put(objData);
request.onsuccess = function () {
console.log('添加或更新数据成功');
}
request.onerror = function () {
console.log('更新数据失败');
}
获取数据
var transaction = DB.transaction([tableName], 'readwrite'),
store = transaction.objectStore(tableName);
/***** 这里有几种查询数据的方式 ******/
// var request = store.get(key); 通过key值查询某一条数据
// var request = store.getAll(); 查询某一个表的所有数据
// 通过游标查询数据(field为createIndex创建的索引字段)
var index = store.index(field),
request = index.openCursor(); // 查询所有数据
request = index.openCursor(IDBKeyRange.only(val)); // 查询field == val的数据
request = index.openCursor(IDBKeyRange.lowerBound(val, false)); // 查询field >= val的数据
request = index.openCursor(IDBKeyRange.lowerBound(val, true)); // 查询field > val的数据
request = index.openCursor(IDBKeyRange.upperBound(val, false)); // 查询field <= val的数据 request = index.openCursor(IDBKeyRange.upperBound(val, true)); // 查询field < val的数据 request = index.openCursor(IDBKeyRange.bound(lower, upper, true/false, true/false)); // 查询lower至upper的数据,true不包含边界,false包含边界 request.onsuccess = function () { console.log('查询数据成功'); } request.onerror = function () { console.log('查询数据失败'); }
封装后的文件
封装之后所有的执行条件都可以写为 `field` == 1 && ((`field1` >= 3 || `field2` != 'name') && `field3` <= 4 || `field4` < 5) 或 1 或 true 格式
运算符支持()、&&、||、==、>=、>、<=、<、!=、like,查询的字段名需要加上``,模糊查询时关键字(like)两边必须加上空格
添加数据时如果传一个数组则批量添加多条数据
查看详情曾经遇到的问题
问题描述
在做一个在线聊天系统的时候用了indexedDB,为了避免消息不断积累数据库变大,每次打开页面的时候都会先执行一次删除数据库再新建,然后就导致了在同一个浏览器的多个标签中打开该页面,数据库卡死无法进行任何操作
原因分析
因为indexedDB的信赖/安全原则,相同域名下在同一个页面下的不同标签页是共享的同一个数据库。打开第一个标签页时创建了数据库连接,再打开第二个标签页执行删除数据库就会因连接未全部关闭而出错
解决方案
if(!sessionStorage.getItem('delSign')){
window.indexedDB.deleteDatabase('DBName');
sessionStorage.setItem('delSign', 1);
}
window.indexedDB.open('DBName', 1);
一个浏览器会话中,只在第一次打开该页面时执行删除数据库操作