概念
IndexedDB 是一种底层 API,用于在客户端存储大量的结构化数据(也包括文件/二进制大型对象(blobs))。该 API 使用索引实现对数据的高性能搜索。虽然 Web Storage 在存储较少量的数据很有用,但对于存储更大量的结构化数据来说力不从心。而 IndexedDB 提供了这种场景的解决方案。
意思就是IndexedDB主要用来客户端存储大量数据而生的
indexedeDB特点
- 键值对存储,所有对象都可存储
- 异步,操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。
- 支持事务。一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。
- 同源限制,不能访问跨域的数据库
- 支持二进制存储。
- 存储空间大,一般不小于250MB,无上限
浏览器存储的方式
数据库操作
游标cursor:可以把游标想象为一个指针,比如我们要查询满足某一条件的所有数据时,就需要用到游标,我们让游标一行一行的往下走,游标走到的地方便会返回这一行数据,此时我们便可对此行数据进行判断,是否满足条件。 只能通过主键、索引、游标方式查询数据。
创建或打开数据库
window.indexedDB.open(DBName,version)
// 兼容浏览器
var indexedDB =
window.indexedDB ||
window.mozIndexedDB ||
window.webkitIndexedDB ||
window.msIndexedDB;
//indexedDB数据库.open("数据库名字","版本号-不填默认1-填写只能是整数") 没有创建 有打开库
const request = indexedDB.open('myDatabase', 1);
request.addEventListener('success', e => {
console.log("连接数据库成功");
});
request.addEventListener('error', e => {
console.log("连接数据库失败");
});
创建删除一个对象仓库
createObjectStore(storeName,para)第一个是对象仓库的名字,在同一数据库中,仓库名不能重复.第二个是可选参数.用于指定数据的主键,以及是否自增主键
deleteObjectStore(storeName)删除对象仓库
const request = indexedDB.open('myDatabase', 2);
request.addEventListener('upgradeneeded', e => {
const db1:any=e
const db = db1?.target.result; //数据库对象
//将主键设置为keyId
const store = db.createObjectStore('storeInfo', {keyPath: 'keyId', autoIncrement: false});
console.log('创建对象仓库成功');
// 删除仓库对象(删除表格)
db.deleteObjectStore('storeInfo');
});
要创建一个对象仓库必须在upgradeneeded事件中,而upgradeneeded事件只会在版本号更新的时候触发.这是因为indexedDB API中不允许数据库中的数据仓库在同一版本中发生变化
创建事务
transaction(storeName,pattern)第一参数对象仓库名称,第二参数创建的事务模式readonly只读,readwrite读写
const request = indexedDB.open('myDatabase', 3);
request.addEventListener('success', e => {
const db1:any=e
const db = db1?.target.result;
//创建事务
const tx = db.transaction('storeInfo','readwrite');
});
操作数据
add() : 增加数据。接收一个参数,为需要保存到对象仓库中的对象。
put() : 增加或修改数据。接收一个参数,为需要保存到对象仓库中的对象。
get() : 获取数据。接收一个参数,为需要获取数据的主键值。
delete() : 删除数据。接收一个参数,为需要获取数据的主键值
注:add 和 put 的作用类似, put 保存数据时,如果该数据的主键在数据库中已经有相同主键的时候,则会修改数据库中对应主键的对象,而使用 add 保存数据,如果该主键已经存在,则保存失败
1 数据增删改查
const request = indexedDB.open('myDatabase', 4);
request.addEventListener('success', e => {
const db = e.target.result;
const tx = db.transaction('storeInfo','readwrite');
const store = tx.objectStore('storeInfo');
// 保存数据
const reqAdd = store.add({'keyId': 1, 'userName': '张三', 'age': 24});
reqAdd.addEventListener('success', e => {
console.log('保存成功')
})
// 获取数据 参数是主键值
const reqGet = store.get(1);
reqGet.addEventListener('success', e => {
console.log(reqGet.result.userName); // 张三
})
// 删除数据
const reqDelete = store.delete(1);
reqDelete.addEventListener('success', e => {
console.log('删除数据成功');
})
});
2 使用游标查询
// boundRange 表示主键值从1到10(包含1和10)的集合。
// 如果第三个参数为true,则表示不包含最小键值1,如果第四参数为true,则表示不包含最大键值10,默认都为false
var boundRange = IDBKeyRange.bound(1, 10, false, false);
// onlyRange 表示由一个主键值的集合。only() 参数则为主键值,整数类型。
var onlyRange = IDBKeyRange.only(1);
// lowerRaneg 表示大于等于1的主键值的集合。
// 第二个参数可选,为true则表示不包含最小主键1,false则包含,默认为false
var lowerRange = IDBKeyRange.lowerBound(1, false);
// upperRange 表示小于等于10的主键值的集合。
// 第二个参数可选,为true则表示不包含最大主键10,false则包含,默认为false
var upperRange = IDBKeyRange.upperBound(10, false);
next : 游标中的数据按主键值升序排列,主键值相等的数据都被读取
nextunique : 游标中的数据按主键值升序排列,主键值相等只读取第一条数据
prev : 游标中的数据按主键值降序排列,主键值相等的数据都被读取
prevunique : 游标中的数据按主键值降序排列,主键值相等只读取第一条数据
// boundRange 表示主键值从1到10(包含1和10)的集合。
// 如果第三个参数为true,则表示不包含最小键值1,如果第四参数为true,则表示不包含最大键值10,默认都为false
var boundRange = IDBKeyRange.bound(1, 10, false, false);
// onlyRange 表示由一个主键值的集合。only() 参数则为主键值,整数类型。
var onlyRange = IDBKeyRange.only(1);
// lowerRaneg 表示大于等于1的主键值的集合。
// 第二个参数可选,为true则表示不包含最小主键1,false则包含,默认为false
var lowerRange = IDBKeyRange.lowerBound(1, false);
// upperRange 表示小于等于10的主键值的集合。
// 第二个参数可选,为true则表示不包含最大主键10,false则包含,默认为false
var upperRange = IDBKeyRange.upperBound(10, false);
3 使用索引游标查询
createIndex(name,keyPath,optionalParameters)
// boundRange 表示主键值从1到10(包含1和10)的集合。
// 如果第三个参数为true,则表示不包含最小键值1,如果第四参数为true,则表示不包含最大键值10,默认都为false
var boundRange = IDBKeyRange.bound(1, 10, false, false);
// onlyRange 表示由一个主键值的集合。only() 参数则为主键值,整数类型。
var onlyRange = IDBKeyRange.only(1);
// lowerRaneg 表示大于等于1的主键值的集合。
// 第二个参数可选,为true则表示不包含最小主键1,false则包含,默认为false
var lowerRange = IDBKeyRange.lowerBound(1, false);
// upperRange 表示小于等于10的主键值的集合。
// 第二个参数可选,为true则表示不包含最大主键10,false则包含,默认为false
var upperRange = IDBKeyRange.upperBound(10, false);
4 复合索引查询
const request = indexedDB.open('myDatabase', 6);
request.addEventListener('upgradeneeded', e => {
const db = e.target.result;
const store = db.createObjectStore('storeInfo', {keyPath: 'keyId', autoIncrement: false});
//创建了多条索引.
store.createIndex('name','username',{unique: false})
store.createIndex('age',"userage",{unique: false})
// 创建复合索引
store.createIndex("name_age", ["name","age"], { unique: false });
});
const arr = []
request.addEventListener('success', e => {
const db = e.target.result;//数据库对象
const tx = db.transaction('storeInfo','readwrite');//事务
const store = tx.objectStore('storeInfo');//对象仓库
//使用索引
const index = store.index('name_age');
//游标
const req = index.openCursor(IDBKeyRange.bound(['李四',12],['李四','']));
req.addEventListener('success', e => {
const cursor = e.target.result;
if(cursor){
arr.push(cursor.value)
console.log(cursor.value,'复合索引');
cursor.continue();
}else{
console.log('检索结束');
}
})
});
5 索引和游标分页查询
//通过索引和游标分页查询记录
let list:any = [];
let counter = 0; // 计数器
let advanced = true; // 是否跳过多少条查询
let page = 1; // 页码
let pageSize = 3; //查询条数
const request = store.index('name').openCursor(IDBKeyRange.only('哈哈'));
request.onsuccess = function (e:any) {
var cursor = e.target.result;
if (page > 1 && advanced) {
advanced = false;
cursor.advance((page - 1) * pageSize); // 跳过多少条
return;
}
if (cursor) {
console.log(cursor,"ppq")
// 必须要检查
counter++;
if (counter < pageSize) {
list.push(cursor.value)
cursor.continue(); // 遍历了存储对象中的所有内容
} else {
cursor = null;
console.log("分页查询结果", list);
}
} else {
console.log("分页查询结果2", list);
}
};
request.onerror = function (e:any) { };
6 模糊查询
//模糊查询
let inpname = "嘻嘻" //查询是值
let list:any = [];
let bol = true;
let nameArr = inpname.split("");
if (db != null) {
const request = store.index('name').openCursor()
request.onsuccess = (e:any) => {
if (request.result) {
let cursor = request.result;
//模糊查询按字符串查找
bol = nameArr.every(value => {
return cursor.key.indexOf(value) > -1;
});
if (bol) {
list.push(cursor.value);
}
cursor.continue();
} else {
console.log("数据为空");
}
};
request.onerror = (e:any) => {
console.log("遍历失败", e);
};
}
删除数据库
window.indexedDB.deleteDatabase(databaseName);