三、indexedDB实操

500 阅读6分钟

IndexedDB所有针对仓库的操作都是基于事务的。

1、创建或连接数据库

代码如下:


/**
 * 打开数据库
 * @param {object} dbName 数据库的名字
 * @param {string} storeName 仓库名称
 * @param {string} version 数据库的版本
 * @return {object} 该函数会返回一个数据库实例
 */
function openDB(dbName, version = 1) {
    return new Promise((resolve, reject) => {

        //兼容浏览器
        var indexedDB =
            window.indexedDB ||
            window.mozIndexedDB ||
            window.webkitIndexedDB ||
            window.msIndexedDB;

        let db;

        //打开数据库,若没有则会创建
        const request = indexedDB.open(dbName, version);

        //数据库打开成功回调
        request.onsuccess = function (event) {
            db = event.target.result; //数据库对象
            console.log("数据库打开成功");
            resolve(db);
        };

        //数据库打开失败的回调
        request.onerror = function (event) {
            console.log("数据库打开报错");
        };

        //数据库有更新时候的回调
        request.onupgradeneeded = function (event) {
            //数据库创建或升级的时候会触发
            console.log("onupgradeneeded");
            db = event.target.result; //数据库对象
            var objectStore;
            //创建存储库
            objectStore = db.createObjectStore("users", {
                keyPath: "uuid", //这是主键
                //autoIncrement: true //实现自增
            });
            //创建索引,在后面查询数据的时候可以根据索引查
            objectStore.createIndex("uuid", "uuid", { unique: true });
            objectStore.createIndex("name", "name", { unique: false });
            objectStore.createIndex("age", "age", {
                unique: false,
            });
        };
    });
}

我们将创建数据库的操作封装成了一个函数,并且该函数返回一个promise对象,使得在调用的时候可以链式调用,函数主要接收两个参数:数据库名称、数据库版本。函数内部主要有三个回调函数,分别是:

  • onsuccess:数据库打开成功或者创建成功后的回调,这里我们将数据库实例返回了出去。
  • onerror:数据库打开或创建失败后的回调。
  • onupgradeneeded:当数据库版本有变化的时候会执行该函数,比如我们想创建新的存储库(表),就可以在该函数里面操作,更新数据库版本即可。

2、插入数据

代码如下:


/**
 * 新增数据
 * @param {object} db 数据库实例
 * @param {string} storeName 仓库名称
 * @param {string} data 数据
 */
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("数据写入失败");
    };
}

IndexedDB插入数据需要通过事务来进行操作,插入的方法也很简单,利用IndexedDB提供的add方法即可,这里我们同样将插入数据的操作封装成了一个函数,接收三个参数,分别如下:

  • db:在创建或连接数据库时,返回的db实例,需要那个时候保存下来。
  • storeName:仓库名称(或者表名),在创建或连接数据库时我们就已经创建好了仓库。
  • data:需要插入的数据,通常是一个对象

【注意】: 插入的数据是一个对象,而且必须包含我们声明的索引键值对。

3、通过主键读取数据

代码如下:


/**
 * 通过主键读取数据
 * @param {object} db 数据库实例
 * @param {string} storeName 仓库名称
 * @param {string} key 主键值
 */
function getDataByKey(db, storeName, key) {
    var transaction = db.transaction([storeName]); //事务
    var objectStore = transaction.objectStore(storeName); //仓库对象
    var request = objectStore.get(key); //通过主键获取数据
    // var request = objectStore.getAll(); 

    request.onerror = function (event) {
        console.log("事务失败");
    };

    request.onsuccess = function (event) {
        console.log("主键查询结果: ", request.result);
    };
}

主键即刚刚我们在创建数据库时声明的keyPath,通过主键只能查询出一条数据

objectStore.getAll() 可以获取所有数据!!!

4、通过游标查询数据

代码如下:


/**
 * 通过游标读取数据
 * @param {object} db 数据库实例
 * @param {string} storeName 仓库名称
 */
function cursorGetData(db, storeName) {
    let list = [];
    var store = db
        .transaction(storeName, "readwrite") //事务
        .objectStore(storeName); //仓库对象
    var request = store.openCursor(); //指针对象
    //游标开启成功,逐行读数据
    request.onsuccess = function (e) {
        var cursor = e.target.result;
        if (cursor) {
            //必须要检查
            list.push(cursor.value);
            cursor.continue(); //遍历了存储对象中的所有内容
        } else {
            console.log("游标读取的数据:", list);
        }
    };
}

上面函数开启了一个游标,然后逐行读取数据,存入数组,最终得到整个仓库的所有数据。

5、通过索引查询数据

代码如下:


/**
 * 通过索引读取数据
 * @param {object} db 数据库实例
 * @param {string} storeName 仓库名称
 * @param {string} indexName 索引名称
 * @param {string} indexValue 索引值
 */
function getDataByIndex(db, storeName, indexName, indexValue) {
    var store = db.transaction(storeName, "readwrite").objectStore(storeName);
    var request = store.index(indexName).get(indexValue);
    request.onerror = function () {
        console.log("事务失败");
    };
    request.onsuccess = function (e) {
        var result = e.target.result;
        console.log("索引查询结果:", result);
    };
}

6、通过索引和游标查询数据

代码如下:


/**
 * 通过索引和游标查询记录
 * @param {object} db 数据库实例
 * @param {string} storeName 仓库名称
 * @param {string} indexName 索引名称
 * @param {string} indexValue 索引值
 */
function cursorGetDataByIndex(db, storeName, indexName, indexValue) {
    let list = [];
    var store = db.transaction(storeName, "readwrite").objectStore(storeName); //仓库对象
    var request = store
        .index(indexName) //索引对象
        .openCursor(IDBKeyRange.only(indexValue)); //指针对象

    request.onsuccess = function (e) {
        var cursor = e.target.result;
        if (cursor) {
            //必须要检查
            list.push(cursor.value);
            cursor.continue(); //遍历了存储对象中的所有内容
        } else {
            console.log("游标索引查询结果:", list);
        }
    };

    request.onerror = function (e) {
        console.log(e, '查询失败');
    };
}

7、通过索引和游标分页查询

代码如下:


/**
 * 通过索引和游标分页查询记录
 * @param {object} db 数据库实例
 * @param {string} storeName 仓库名称
 * @param {string} indexName 索引名称
 * @param {string} indexValue 索引值
 * @param {number} page 页码
 * @param {number} pageSize 查询条数
 */
function cursorGetDataByIndexAndPage(
    db,
    storeName,
    indexName,
    indexValue,
    page,
    pageSize
) {
    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.onsuccess = function (e) {
        var 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 {
                cursor = null;
                console.log("分页查询结果", list);
            }
        } else {
            console.log("分页查询结果", list);
        }
    };

    request.onerror = function (e) {
        console.log(e, '查询失败');
    };
}

8、更新数据

代码如下:


/**
 * 更新数据
 * @param {object} db 数据库实例
 * @param {string} storeName 仓库名称
 * @param {object} data 数据
 */
function updateDB(db, storeName, data) {
    var request = db
        .transaction([storeName], "readwrite") //事务对象
        .objectStore(storeName) //仓库对象
        .put(data);

    request.onsuccess = function () {
        console.log("数据更新成功");
    };

    request.onerror = function () {
        console.log("数据更新失败");
    };
}

9、通过主键删除数据

代码如下:


/**
 * 通过主键删除数据
 * @param {object} db 数据库实例
 * @param {string} storeName 仓库名称
 * @param {object} id 主键值
 */
function deleteDB(db, storeName, id) {
    var request = db
        .transaction([storeName], "readwrite")
        .objectStore(storeName)
        .delete(id);

    request.onsuccess = function () {
        console.log("数据删除成功");
    };

    request.onerror = function () {
        console.log("数据删除失败");
    };
}

10、通过索引和游标删除指定的数据

代码如下:


/**
 * 通过索引和游标删除指定的数据
 * @param {object} db 数据库实例
 * @param {string} storeName 仓库名称
 * @param {string} indexName 索引名
 * @param {object} indexValue 索引值
 */
function cursorDelete(db, storeName, indexName, indexValue) {
    var store = db.transaction(storeName, "readwrite").objectStore(storeName);
    var request = store
        .index(indexName) //索引对象
        .openCursor(IDBKeyRange.only(indexValue)); //指针对象

    request.onsuccess = function (e) {
        var cursor = e.target.result;
        var deleteRequest;
        if (cursor) {
            deleteRequest = cursor.delete(); //请求删除当前项
            deleteRequest.onerror = function () {
                console.log("游标删除该记录失败");
            };
            deleteRequest.onsuccess = function () {
                console.log("游标删除该记录成功");
            };
            cursor.continue();
        }
    };

    request.onerror = function (e) {
        console.log(e, '删除失败');
    };
}

11、关闭数据库

代码如下:


/**
 * 关闭数据库
 * @param {object} db 数据库实例
 */
function closeDB(db) {
    db.close();
    console.log("数据库已关闭");
}

12、删除数据库

代码如下:


/**
 * 删除数据库
 * @param {object} dbName 数据库名称
 */
function deleteDBAll(dbName) {
    console.log(dbName);
    let deleteRequest = window.indexedDB.deleteDatabase(dbName);
    deleteRequest.onerror = function (event) {
        console.log("删除失败");
    };
    deleteRequest.onsuccess = function (event) {
        console.log("删除成功");
    };
}

(完)

友情感谢