localStorage 不够用?试试 IndexedDB !
当前位置:点晴教程→知识管理交流
→『 技术文档交流 』
一、前言在前端开发过程中,偶尔会遇到需要存储大量数据在前端的情况。localstorage 单个域名存储大小只有5M,此时 indexedDB 便派上了用场。
可使用 StorageManager API 来查询当前源的配额使用情况和剩余空间 提示:无痕模式下,可用空间会小很多。以我的电脑为例,使用Chrome浏览器正常模式下配额142.39 GB。使用Chrome浏览器无痕模式下配额1.59 GB。但不管怎么说,也比localstorage大不少 兼容性目前良好:
indexedDB 有较大的存储空间,这是它最大的优点。它的缺点也很明显,API比较复杂,有上手难度。如果你不在意使用细节,或者项目中可以随意添加第三方包,而不在乎项目的体积大小,可直接使用库: 二、特点
三、基础使用1. 新建数据库(indexDB)open方法接收两个参数,第一个是数据库名,第二个是数据库的版本号 在操作数据的时候,需要更新版本号才生效
创建一个对象仓库必须在upgradeneeded事件中,而upgradeneeded事件只会在版本号更新的时候触发,这是因为不允许数据库中的数据仓库在同一版本中发生变化 createObjectStore方法接受两个参数,第一个参数是对象仓库的名称,第二个参数用于指定数据的主键,主键的值必须是唯一且非空的,以及是否自增主键。
keyPath的值可以是一个数组,例如需要存储不同用户设置的标签颜色。用户的id和标签的key可共同作为主键,以满足主键值的唯一性。 db.createObjectStore("Users", { keyPath: ['userId', 'key'] }); 3. 事务IndexDB的读/写,都要通过事务操作。 特点一:事务保证数据库操作要么全部成功,要么全部失败进行回滚,恢复到上一状态。 代码高亮:
// 开启事务 const transaction = db.transaction("Users", "readwrite"); 第一个参数是要操作的表的名称 第二个是要创建的事务模式,如readonly只能进行读操作,readwrite能进行读写操作 特点二:它是自动提交的。即所有请求都已完成,并且事件循环再次变为空闲状态时,事务会自动提交并随之关闭。这意味着,不能在异步中调用事务 4. 增加数据 add1. 增加单条数据 在数据库连接成功的onsuccess事件中,进行数据操作 在开发者工具中,点击 Refresh database,可以看到数据已被添加到Users对象仓库中 2. 增加多条数据 通过监听事务的oncomplete事件,判断是否操作完成
5. 读取数据 get
代码高亮:
request.onsuccess = function (res) { const db = res.target.result; if (db.objectStoreNames.contains("Users")) { //开启事务,只允许读操作 const transaction = db.transaction("Users", "readonly"); //获取对象存储空间,进行数据操作 const store = transaction.objectStore("Users"); //传入主键值 const reqGet = store.get(1); reqGet.onsuccess = function (event) { if (event.target.result) { console.log("数据获取成功", event.target.result); } else { console.log("未获取到数据"); } }; reqGet.onerror = function (event) { console.log("数据获取失败", event); }; } }; 如果主键是由多个值组成,例如创建表时,keyPath是个数组 那么取值时,也通过数组取值
6. 更新数据 put使用 put 进行数据操作时,“无则增,有则改”。如果主键不存在,则新建数据。如果主键存在,则更新数据。除非明确数据只能新增,不能更新,其余情况下,put 可以代替add。 代码高亮:
request.onsuccess = function (res) { const db = res.target.result; if (db.objectStoreNames.contains("Users")) { //开启事务,允许读写操作 const transaction = db.transaction("Users", "readwrite"); //获取对象存储空间,进行数据操作 const store = transaction.objectStore("Users"); //put方法根据主键值更新数据 const reqPut = store.put({ userId: 1, userName: "张三", age: 20 }); reqPut.onsuccess = function (event) { console.log("数据更新成功", event); }; reqPut.onerror = function (event) { console.log("数据更新失败", event); }; } }; 7. 删除数据 delete四、进阶1. IDBKeyRangeIDBKeyRange:用于定义和限制在数据库查询中使用的键的范围,从而根据条件查询多条数据 1. 精确匹配 查找主键值为1的数据 2. 范围匹配 查找主键值为1到10的数据 如果第三个参数为true,则表示不包含最小键值1,如果第四参数为true,则表示不包含最大键值10,默认都为false 3. 上下界匹配 (1)下界匹配 第二个参数可选,为true则表示不包含最小主键1,false则包含,默认为false 代码高亮:
const range = IDBKeyRange.lowerBound(1, false); 2)上界匹配 第二个参数可选,为true则表示不包含最大主键10,false则包含,默认为false 当主键由一个字段组成,并且根据主键查询时,可使用 store.getAll+ IDBKeyRange 直接查询数据。 示例:获取所有主键值小于等于10的数据 2. 游标作用:选定范围,并遍历和操作数据 range:表示范围,IDBKeyRange的值 direction:表示方向,next 升序(默认);nextunique 升序,索引值相等则只读第一条;prev 降序;prevunique 降序,索引值相等则只读第一条; 代码高亮:
request.onsuccess = function (res) { const db = res.target.result; //如果存在Users表 if (db.objectStoreNames.contains("Users")) { //开启事务 const transaction = db.transaction("Users", "readwrite"); //获取对象存储空间,进行数据操作 const store = transaction.objectStore("Users"); //主键1到10 const range = IDBKeyRange.bound(1, 10); const request = store.openCursor(range); request.onsuccess = function (event) { const cursor = event.target.result; if (cursor) { console.log(cursor.value); //拿到数据 // cursor.updata(value) 更新数据 // cursor.delete() 删除数据 // cursor.advance(count) 向前跳过指定数量的记录,可用作分页 cursor.continue();//继续读取下一条 } else { console.log("没有更多result"); } }; request.onerror = function (event) { console.log("数据查找失败", event); }; } }; 3. 索引索引极大地扩展了数据库的查询能力,上述示例是基于主键查询。如果一个数据结构为{ userId: 1, userName: "张三", age: 20 },其中userId为主键,那么要查询所有age小于18的数据时,就需要借助索引。 name:索引名称 keyPath:要索引的对象属性,可以是单个key值,也可以是key值组成的数组 optionalParameters:可选参数{unique, multiEntry} unique:指定被索引的属性值是否可以重复,为true代表不能重复,为false时可以重复。默认false multiEntry:当第二个参数keyPath为数组时,如果multiEntry是true,则会以数组中的每个元素建立一条索引。如果是false,将整个数组作为一个单一的复合键存入索引。默认为false。 1. 创建索引 在数据库版本升级时(在 onupgradeneeded 事件中)创建 2. 获取单个值 get 获取单个值的前提,创建索引时unique为true,否则查询到的结果一直为undefined 查询值 代码高亮:
const transaction = db.transaction("Users", "readonly"); const store = transaction.objectStore("Users"); const index = store.index("ageIndex"); const request = index.get(20); request.onsuccess = function (event) { let user = event.target.result; console.log("Found user:", user); }; 3. 获取所有值 getAll 不管值是否唯一,获取所有值 4. 通过索引打开游标 可对范围内的数据进行读取或修改
为了更方便的使用,可以将IndexDB的操作封装成一个类
参考文章:原文链接 该文章在 2026/2/6 16:32:10 编辑过 |
相关文章
正在查询... |