为什么学习indexDB,它虽然是在浏览器上,但是实际存储是跟本地的磁盘相关,所以当存储大文件时数据,尤其是在离线存储和大数据量处理方面。,就可以使用indexDB了
了解indexDB
indexDB是浏览器提供的非线性数据库,由仓库-表-索引组成,表之间是无法关联,因为是非线性。
indexDB基础使用
来自b站学习
方法
function openDB(dbName, version = 1) {
return new Promise((resolve, reject) => {
// 兼容浏览器
const indexDB = window.indexedDB || window.mozIndexDB || window.webkitIndexDB || window.msIndexDB;
let db;
// 打开数据库,没有就创建
const request = indexDB.open(dbName, version);
// 数据打开并回调
request.onsuccess = function (event) {
db = event.target.result; // 数据对象
console.log('打开成功')
resolve(db)
};
// 数据库打开失败回调
request.onerror = function (event) {
console.log('数据库打开失败');
reject('数据库打开失败')
}
// 数据库有更新时就回调,创建表时,要版本更新
request.onupgradeneeded = function (event) {
// 创建或升级时会触发
console.log('upgradeneeded')
db = event.target.result; // 数据对象
var objectStore; // 仓库
// 在dbName数据库,创建一个表
objectStore = db.createObjectStore('bao', {
keyPath: 'squencdId', // 这是主键
// autoIncrement:true //实现自增1,2,3这种
})
// 创建索引,在后面查询数据的时候可以根据索引查 也可以理解为建表的结构
// objectStore.createIndex(库中某个字段,键的名字,对象[unique:是否唯一])
objectStore.createIndex('link', 'link', { unique: false });
objectStore.createIndex('squencdId', "squencdId", { unique: true });
objectStore.createIndex('messageType', "messageType", { unique: false });
}
})
}
// 插入数据
function addData(db, storeName, data) {
// 事务对象 指定表格名称和操作模式(只读或读写) // 仓库对象
var request = db.transaction([storeName], "readwrite").objectStore(storeName).add(data);
request.onsuccess = function (event) {
console.log('数据写入成功')
}
request.onerror = function (event) {
console.log('数据读写失败')
}
}
// indexDB查询只能通过主键、游标、索引查询
// 通过主键查询,这里的主键是的squencdId所对应的值 数据库对象,表名,主键的值
function getDataKey(db, storeName, keyValue) {
return new Promise((resolve, reject) => {
const transaction = db.transaction([storeName]); // 事务
const objectStore = transaction.objectStore(storeName); // 仓库对象
const request = objectStore.get(keyValue);
request.onerror = function (event) {
console.log('事务失败')
}
request.onsuccess = function (event) {
console.log('查询结果', event.target.result);
resolve(event.target.result)
}
})
}
// 游标查询数据 逐行读取数据,存入数组,最终得到整个仓库的所以数据。
function cursorGetData(db, storeName) {
return new Promise((resolve, reject) => {
let list = [];
var store = db.transaction(storeName, 'readwrite').objectStore(storeName);
var request = store.openCursor(); // 开启游标对象
// 游标对象开启成功
request.onsuccess = function (e) {
var cursor = e.target.result;
// console.log('cursor',cursor)
// 必须判断,有值才cursor.continue();
if (cursor) {
list.push(cursor.value);
cursor.continue(); // 遍历了存储对象中所有内容
} else {
console.log('游标读取数据', list)
resolve(list)
}
}
})
}
// 索引查询
function getDataByIndex(db, storeName, indexName, indexValue) {
return new Promise((resolve, reject) => {
var store = db.transaction(storeName, 'readwrite').objectStore(storeName);
var request = store.index(indexName).get(indexValue);
request.onerror = function () {
console.log('事务失败')
}
request.onsuccess = function (e) {
const result = e.target.result;
console.log('索引查询结果', result);
resolve(result)
}
})
}
// 通过索引和游标一起查询
function cursorGetDataByIndex(db, storeName, indexName, indexValue) {
return new Promise((resolve, reject) => {
let list = [];
var store = db.transaction(storeName, 'readwrite').objectStore(storeName);
var request = store.index(indexName).openCursor(IDBKeyRange.only(indexValue));
request.onerror = function () {
console.log('事务失败')
}
request.onsuccess = function (e) {
const cursor = e.target.result;
if (cursor) {
list.push(cursor.value);
cursor.continue(); // 遍历了存储对象中所有内容
} else {
console.log('游标索引查询结果', list)
resolve(list)
}
}
})
}
// 通过索引和游标的分页查询
function cursorGetDataByIndexAndPage(db, storeName, indexName, indexValue, page, pageSize) {
return new Promise((resolve, reject) => {
cursorGetDataByIndex(db, storeName, indexName, indexValue).then(res => {
const total = res.length;
const totalPage = Math.ceil(total / pageSize);
if( totalPage < page){
resolve({
data: [],
total: total,
totalPage: totalPage,
current: page,
size: pageSize
})
return
}
let list = [];
let counter = 0; // 计数器
let advanced = true; // 是否跳过查询
var store = db.transaction(storeName, 'readwrite').objectStore(storeName);
var request = store.index(indexName).openCursor(IDBKeyRange.only(indexValue));
request.onerror = function () {
console.log('事务失败')
}
request.onsuccess = function (e) {
let cursor = e.target.result;
if (page > 1 && advanced) {
advanced = false;
cursor.advance((page - 1) * pageSize); // 跳过多少条
return
}
if (cursor) {
list.push(cursor.value);
counter++;
if (counter < pageSize) {
cursor.continue(); // 遍历了存储对象中所有内容
} else {
console.log('游标索引分页查询结果', list)
cursor = null;
resolve({
data: list,
total: total,
totalPage: totalPage,
current: page,
size: pageSize
});
}
} else {
console.log('游标索引分页查询结果', list)
resolve({
data: list,
total: total,
totalPage: totalPage,
current: page,
size: pageSize
});
}
}
})
})
}
// 更新数据 主键值存在就更新,不存在就添加
function updataDB(db,storeName,data){
return new Promise((resolve, reject) => {
var request = db.transaction(storeName, 'readwrite').objectStore(storeName).put(data);
request.onerror = function () {
console.log('数据更新失败')
reject()
}
request.onsuccess = function (e) {
console.log('数据更新成功')
resolve()
}
})
}
// 通过主键值,删除数据
function deleteDB(db,storeName,id){
return new Promise((resolve, reject) => {
var request = db.transaction(storeName, 'readwrite').objectStore(storeName).delete(id);
request.onerror = function () {
console.log('删除失败')
reject()
}
request.onsuccess = function (e) {
console.log('删除成功')
resolve()
}
})
}
// 通过索引和游标,删除数据
function cursorDelete(db,storeName,indexName,indexValue){
return new Promise((resolve, reject) => {
var store = db.transaction(storeName, 'readwrite').objectStore(storeName)
var request = store.index(indexName).openCursor(IDBKeyRange.only(indexValue));
request.onerror = function () {
console.log('删除失败')
reject()
}
request.onsuccess = function (e) {
var cursor = e.target.result;
var deleteRequest;
if(cursor){
deleteRequest = cursor.delete();
deleteRequest.onerror = function(){
console.log('游标删除数据失败')
reject();
};
deleteRequest.onsuccess = function(){
console.log('游标删除数据成功')
resolve();
}
cursor.continue();
}
resolve()
}
})
}
function closeDB(db){
db.close();
console.log('数据库已关闭')
}
使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="./indexDB.js"></script>
<title>Document</title>
</head>
<body>
<button id="dbBtn">打开数据库</button>
<script>
const dbBtnDom = document.getElementById('dbBtn');
var hasOpen = false;
var db;
// 创建数据库
const openTheDB = async () => {
db = await openDB('test', 1);
// 插入数据
const data = {
link: '1',
squencdId: Math.floor(Math.random() * 100),
messageType: Math.floor(Math.random() * 100)
}
// addData(db, 'bao', data)
// 通过主键查询
getDataKey(db, 'bao', 15).then(res => {
// console.log('查询结果',res)
})
// 游标查询
cursorGetData(db, 'bao');
// 索引查询 若是值有重复,只返回查询索引值的第一个
getDataByIndex(db, 'bao', 'link', '1');
// 通过索引和游标一起查询,只要link='1'都返回
cursorGetDataByIndex(db, 'bao', 'link', '1')
// 通过索引和游标的分页查询
cursorGetDataByIndexAndPage(db, 'bao', 'link', '1', 1, 5).then(res => {
console.log('通过索引和游标的分页查询', res);
});
// 更新数据
updataDB(db, 'bao', { link: '1', squencdId: 7, messageType: 12 });
// 删除数据
// deleteDB(db,'bao',7);
// 通过索引和游标,删除数据
cursorDelete(db, 'bao', 'messageType', 35)
}
dbBtnDom.onclick = () => {
if (hasOpen) {
dbBtnDom.innerHTML = '打开数据库'
hasOpen = false;
closeDB(db);
db = null;
} else {
hasOpen = true;
dbBtnDom.innerHTML = '关闭数据库';
openTheDB();
}
}
window.addEventListener('beforeunload', function (e) {
e.preventDefault();
closeDB(db);
});
</script>
</body>
</html>