indexedDB的简单使用(增删查改) 以及indexedDB封装

497 阅读5分钟

1. 什么是indexedDB

在浏览器中常见存储方式分了几种

Local stroage
Session stroage
Cookie
indexedDB

  • local Stroage

按浏览器版本以及内核大小不一样可存储最大 5MB - 10MB; 通常用于存储用户数据 无时效性

localStorage.getItem(key)
localStorage.setItem(key,value)
  • Session Stroage

按浏览器版本以及内核大小不一样可存储最大 5MB - 10MB; 通常用于存储一次性数据 网页关闭即清除

sessionStorage.getItem(key)
sessionStorage.setItem(key,value)
  • Cookie

存储最大4KB; 通常用于存储跟踪用户的数据 无时效性 同域名下共享 使用麻烦这里推荐用插件 js-cookie

import Cookies from 'js-cookie'
Cookies.get(key)
Cookies.set(key,value)

理解为浏览器给你提供的一个本地数据库, IndexedDB采用主键方式存储 是异步操作 避免造成浏览器假死,  无时效性 可存储大于250MB 主要取决于你电脑剩下多少空间, 可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)
下面是兼容性

2. indexedDB如何使用

打开数据库建立数据库

建立数据库使用方法 indexedDB.open(数据库名,数据库版本号) 不存在则会自动新建数据库,新建数据库时,默认为1; 建立后会触发三个事件

  • [1] - 触发error事件表示打开或新建失败
  • [2] - 触发success事件表示打开成功
  • [3] - 触发upgradeneeded 事件新建数据库会触发 版本号升级也会触发(主要在里面进行建表删除表 添加索引)
 // 兼容各种浏览器方式
 const indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB; 
    const request = indexedDB.open("device", 1);
        request.onerror = (() => {
            console.log('数据库打开报错');
        })
        request.onsuccess = (() => {
            console.log('数据库打开报错');
        })

        request.onupgradeneeded = ((event) => {
            let objectStore = request.result; //获取数据库实例
            const dbversion = event.target.result.version; //当前版本号
        })

建立表

建立表是通过上面提到的打开数据库后的onupgradeneeded事件内进行

建立表的方法createObjectStore(表名,{ keyPath: 主键}) 主键就是表里的唯一id值,可以自定义主键值也可自动生成

createObjectStore(表名,{ autoIncrement: true }) 除了建立主键外还可以建立索引 索引通过建立表的实例进行创建

createIndex("索引名称","属性",{ unique: false }) unique判断索引值是否可以重复

request.onupgradeneeded = ((event) => {
    let db = request.result; //获取数据库实例
    const objectStore = db.createObjectStore('device', { keyPath: deviceId }); //创建表
    objectStore.createIndex('name', 'name', { unique: false }); // 建立索引
    db.deleteObjectStore('device') // 删除表
})

新增数据

新增需要新建一个事务 transaction(表名,只读(readonly) || 读写(readwrite));建好事务获取表的实例通过objectStore(表名)

表的实例上面有很多个方法 这里记录我用到的

  • [ 1 ] add() // 新增 onsuccess onerror
  • [ 2 ] get() // 主键查找 onsuccess onerror
  • [ 3 ] getAll() // 查询表里所有数据 onsuccess onerror
  • [ 4 ] put() // 修改 onsuccess onerror
  • [ 5 ] delete() // 删除 onsuccess onerror
  • [ 6 ] index().get() // 索引查找 onsuccess onerror
  • [ 7 ] clear() //清空表
  request.onsuccess = ((event) => {
    const db = event.target.result;
    const cameraDeviceTable = db.transaction(['cameraDevice'], 'readwrite').objectStore('cameraDevice')
    cameraDeviceTable.add({
        deviceName: "成都匝道摄像头",
        deviceId: 888,
        status: 1111
    })
})

查找表数据

 request.onsuccess = ((event) => {
    const db = event.target.result;
    const cameraDeviceTable = db.transaction(['cameraDevice'], 'readonly').objectStore('cameraDevice');
    let request;
    //  request =cameraDeviceTable.getAll(); // 查询所有数据
    //  request = cameraDeviceTable.get('354t6-45465-4646') // 主键id查询
     request = cameraDeviceTable.index("deviceName").get("XXX摄像头") // 索引查询
    request.onsuccess = (event) => {
        console.log(request.result, "操作成功");
    };
    // 操作失败
    request.onerror = (event) => {
        console.log("操作失败");
    };
})

修改表数据

 request.onsuccess = ((event) => {
    const db = event.target.result;
    const cameraDeviceTable = db.transaction(['cameraDevice'], 'readwrite').objectStore('cameraDevice');
    let request;
    // request = cameraDeviceTable.get("354t6-45465-4646') // 主键id查询
    request = cameraDeviceTable.index("deviceName").get("XXX摄像头") // 索引查询
    request.onsuccess = (event) => {
        let data = event.target.result
        data.deviceName = '二楼厕所门口摄像头'
        cameraDeviceTable.put(data)
        console.log("操作成功");
    };
    // 操作失败
    request.onerror = (event) => {
        console.log("操作失败");
    };
})

删除表数据

request.onsuccess = ((event) => {
    const db = event.target.result;
    const cameraDeviceTable = db.transaction(['cameraDevice'], 'readwrite').objectStore('cameraDevice');
    let request = cameraDeviceTable.delete('354t6-45465-4646') // 主键id删除
    request.onsuccess = (event) => {

        console.log("操作成功");
    };
    // 操作失败
    request.onerror = (event) => {
        console.log("操作失败");
    };
})

数据库链接关闭 db.close()

3. 怎么封装indexedD

新建indexedDB.js文件 封装转载于点击查看 建议看他的原文我这个是基于他上面进行了一些修改

// 适配不同浏览器
const indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB;
// 新建类
class IndexedDBCache {
    constructor(_dbName) {
        this._db = null; // 数据库
        this._transactionRead = null; // 读取事务
        this._transactionWrite = null, // 写入事务
        this._request = null;
        this._dbName = _dbName; //数据库名
        this._dbversion = 1; //数据库版本
    }
   
   
   initDB(tableData) {
        return new Promise((resolve, reject) => {
            // 已打开过数据库 再次调用则为更新表
            const indexedDBVersion = JSON.parse(localStorage.getItem("indexedDBVersion")) || []
            let dbNameVersion = this._dbversio;
            if (indexedDBVersion && indexedDBVersion.length) {
                let idata = indexedDBVersion.find((i) => i.dbName == this._dbName)?.version;
                if (idata) {
                    dbNameVersion = idata
                }
            }
            if (this._request) {
                this._db.close();
                this._request = null;
                this._request = indexedDB.open(this._dbName, dbNameVersion); // 打开数据库
            } else {
                this._request = indexedDB.open(this._dbName, dbNameVersion); // 打开数据库
            }
            // 数据库初始化成功
            this._request.onsuccess = (event) => {
                // 版本号+1 为了下次重新initDB使用
                const version = Number(event.target.result.version) + 1;
                if (indexedDBVersion && indexedDBVersion.length) {
                    const index = indexedDBVersion.findIndex((i) => i.dbName == this._dbName);
                    if (index != -1) {
                        indexedDBVersion[index].version = version;
                    } else {
                        indexedDBVersion.push({ dbName: this._dbName, version: version });
                    }
                } else {
                    indexedDBVersion = [{ dbName: this._dbName, version: version }]
                }

                localStorage.setItem("indexedDBVersion", JSON.stringify(indexedDBVersion));
                this._db = this._request.result;
                console.log("数据库链接成功!")
                resolve(event);
            };
            // 数据库初始化失败
            this._request.onerror = (event) => {
                reject(event);
            };
            // 数据库初次创建或更新时会触发
            this._request.onupgradeneeded = (event) => {
                const db = this._request.result;
                if (tableData && tableData.length) {
                    tableData.forEach((i) => {
                        // 判断表是否存在创建表
                        if (!db.objectStoreNames.contains(i.tableName)) {
                            let storeOptions = "id" in i ? {
                                keyPath: i.id
                            } : {
                                keyPath: i.id,
                                autoIncrement: true
                            };
                            const objectStore = db.createObjectStore(i.tableName, storeOptions);
                            // 设置索引
                            if (i.indexList && i.indexList.length) {
                                i.indexList.forEach((j) => {
                                    objectStore.createIndex(j)
                                })
                            }
                        }

                    })
                }

                resolve(event);
            };
        });
    }



    /**
     * 通过表名存储新数据
     * @param {String} tableName 表名
     * @param {Array | Object} dataList 要存储的数据
     * @returns 
     */
    addData(tableName, dataList) {
        return new Promise((resolve, reject) => {
            const transaction = this._db.transaction(tableName, "readwrite");
            const objectStore = transaction.objectStore(tableName);
            // 判断需存储类型 分类型存储
            if (dataList?.constructor === Array) {
                dataList.forEach((i) => {
                    var addRequest = objectStore.add(i);
                    addRequest.onerror = (event) => {
                        console.log("操作失败");
                        reject(event);
                    };
                })
            } else {
                var addRequest = objectStore.add(dataList);
                addRequest.onerror = (event) => {
                    console.log("操作失败");
                    reject(event);
                };
            }
            transaction.oncomplete = ((event) => {
                console.log("操作成功");
                resolve(event);
            })

        })
    }

    /**
     * 通过主键读取数据 
     * @param {string} key 要读取的主键值
     * @returns 
     */
    getDataByKey(tableName, key) {
        return new Promise((resolve, reject) => {
            const transaction = this._db.transaction(tableName, "readonly");
            const objectStore = transaction.objectStore(tableName);
            // 通过主键读取数据 有主键则为主键无则返回所有数据
            let request;
            if (key === undefined) {
                request = objectStore.getAll();
            } else {
                /* 
                    objectStore.get(值) 主键查询 
                    objectStore.index(索引).get(值) 索引查询
                */
                request = objectStore.get(key);
            }
            // 操作成功
            request.onsuccess = () => {
                console.log("操作成功");
                resolve(request.result);
            };
            // 操作失败
            request.onerror = (event) => {
                console.log("操作失败");
                reject(event);
            };
        });
    }


    /**
    * 清空表数据
    * @param {string} tableName  表名
    * @returns 
    */
    clearDBTable(tableName) {
        return new Promise((resolve, reject) => {
            const transaction = this._db && this._db.transaction(tableName, "readwrite");
            const store = transaction && transaction.objectStore(tableName);
            const response = store && store.clear();
            // 操作成功
            response.onsuccss = (event) => {
                console.log("清空数据库数据");
                resolve(event);
            };
            // 操作失败
            response.onerror = (event) => {
                reject(event);
            };
        });
    }


    /**
     * 更新表里的数据
     * @param {string} tableName 表名
     * @param {string | Object} keyData  xxx  ||  { keys:'xx' value:'xx' } 获取数据方式
     * @param {Array | Object} newData 要存储的数据
     * 
     */
    updateTableData(tableName, keyData, newData) {
        return new Promise((resolve, reject) => {
            const transaction = this._db.transaction(tableName, "readwrite");
            const objectStore = transaction.objectStore(tableName);
            let request;
            if (keyData?.constructor === String) {
                request = objectStore.get(keyData);
            } else {
                request = objectStore.index(keyData.keys).get(keyData.value);
            }
            request.onsuccess = (event) => {
                let data = newData;
                objectStore.put(data);
                transaction.oncomplete = function (event) {
                    resolve(event.target.result);
                };
            }
            request.onerror = (event) => {
                console.log("更新数据失败")
                reject(event);
            };
        })
    }

    /**
     * 通过主键删除表里的某一条数据
     * @param {string} tableName 表名
     * @param  key 主键
     */
    delteTableData(tableName, key) {
        return new Promise((resolve, reject) => {
            const transaction = this._db.transaction(tableName, "readwrite");
            const objectStore = transaction.objectStore(tableName);
            let request = objectStore.delete(key);
            request.onsuccess = (event) => {
                resolve(event);
            }
            request.onerror = (event) => {
                console.log("更新数据失败")
                reject(event);
            };
        })
    }

    // 关闭数据库链接
    closeDB() {
        this._db.close();
        console.log(`关闭数据库`);
    }

}
export default IndexedDBCache

4. 总结

记录项目中的第三个学习知识点... 以上记录只是我了解的还有很多API我是不了解以及没有写出来的 你们感兴趣的可以自己去看官网。