• 数据存储(二)WebStorage 之 IndexedDB


    参考:《JavaScript 高级程序设计》(第3版)

    扩展:

    数据存储(一)Cookie_不头秃的码农的博客-CSDN博客_cookie存数据

    数据存储(二)WebStorage 之 sessionStorage、globalStorage、localStorage_不头秃的码农的博客-CSDN博客

    Indexed Database API,简称为 IndexedDB,是在浏览器中保存结构化数据的一种数据库,支持保存、读取、查询、搜索等。

    替代了已被废弃的 Web SQL Database API。

    ================ 使用步骤 ================

    1. 建立与数据库的连接

    indexedDB 是一个数据库,使用对象保存数据(不是用表来保存)。一个 indexedDB 数据库,就是一组位于相同命名空间下的对象的集合。

    • 使用 window.indexedDB.open(dbName, version) 打开数据库。
    • 使用 db.close() 关闭数据库、断开数据库连接。db代表数据库实例对象。
    • 使用 window.indexedDB.deleteDatabase(dbName) 删除数据库。(只有在数据库断开连接的情况下才能删除)
    1. // 打开名为 JackDB 的数据库
    2. let request = indexedDB.open("JackDB", 1);
    3. /**
    4. * onupgradeneeded 当创建一个新的数据库或者增加已存在的数据库的版本号,onupgradeneeded 事件会被触发
    5. * onupgradeneeded 是唯一可以修改数据库结构的地方
    6. */
    7. request.onupgradeneeded = function (event) {
    8. // todo something
    9. };
    10. request.onsuccess = function (event) {
    11. // event.target 是 IDBRequest 实例,指向request对象
    12. // event.target.result 指向数据库实例对象
    13. // todo something
    14. };
    15. request.onerror = function (event) {
    16. console.log("数据库打开失败:", event.target.errorCode);
    17. };

    2. 创建对象存储空间

    因仅能在 onupgradeneeded 事件修改数据库结构,所以仅能在此事件里创建存储空间。

    创建对象存储空间时,需要指定一个唯一的键。

    • 可以通过 keyPath 指定主键,
    • 可以通过 autoIncrement: true 设置自增键
    1. request.onupgradeneeded = function (event) {
    2. // event.target 是 IDBRequest 实例,指向 request 对象
    3. db = event.target.result; // event.target.result 是数据库实例对象
    4. let store;
    5. if (!db.objectStoreNames.contains("users")) {
    6. // 创建名为 users 的存储空间
    7. // store = db.createObjectStore("users", { autoIncrement: true }); // autoIncrement 自增主键
    8. store = db.createObjectStore("users", { keyPath: "name" }); // keyPath 主键字段名
    9. }
    10. };

    3. 数据的基本CRUD

    3.1 新增数据

    1. /**
    2. * 写入数据
    3. * @param {IDBDatabase} db 数据库实例
    4. * @param {String | Array} dbName 数据库名
    5. * @param {String} storeName objectStore名
    6. * @param {*} data 待新增的数据
    7. */
    8. function add(db, dbName, storeName, data) {
    9. let request = db
    10. .transaction(dbName, "readwrite") // 新建事务
    11. .objectStore(storeName) // 拿到 IDBObjectStore 对象
    12. .add(data);
    13. request.onsuccess = (event) => {
    14. console.log('写入数据成功',event.target.result)
    15. };
    16. request.onerror = (event) => {
    17. console.log('写入数据失败', event.target.error);
    18. };
    19. request.onabort = (event) => {
    20. console.log('事务回滚', event.target);
    21. };
    22. }

    3.2 修改数据

    1. /**
    2. * 根据主键修改数据(若无此主键,则新增数据)
    3. * @param {IDBDatabase} db 数据库实例
    4. * @param {String | Array} dbName 数据库名
    5. * @param {String} storeName objectStore名
    6. * @param {*} key 主键
    7. */
    8. function update(db, dbName, storeName, data) {
    9. let request = db
    10. .transaction(dbName, "readwrite") // 新建事务
    11. .objectStore(storeName) // 拿到 IDBObjectStore 对象
    12. .put(data);
    13. request.onsuccess = (event) => {
    14. console.log('修改数据成功',event.target.result)
    15. };
    16. request.onerror = (event) => {
    17. console.log('修改数据失败', event.target.error);
    18. };
    19. request.onabort = (event) => {
    20. console.log('事务回滚', event.target);
    21. };
    22. }

    3.3 查询数据

    1. /**
    2. * 根据主键读取数据
    3. * @param {IDBDatabase} db 数据库实例
    4. * @param {String | Array} dbName 数据库名
    5. * @param {String} storeName objectStore名
    6. * @param {*} key 主键
    7. */
    8. function read(db, dbName, storeName, key) {
    9. let request = db
    10. .transaction(dbName, "readwrite") // 新建事务
    11. .objectStore(storeName) // 拿到 IDBObjectStore 对象
    12. .get(key);
    13. request.onsuccess = (event) => {
    14. console.log('读取数据成功',event.target.result)
    15. };
    16. request.onerror = (event) => {
    17. console.log('读取数据失败', event.target.error);
    18. };
    19. request.onabort = (event) => {
    20. console.log('事务回滚', event.target);
    21. };
    22. }

    3.4 删除数据

    1. /**
    2. * 根据主键删除数据
    3. * @param {IDBDatabase} db 数据库实例
    4. * @param {String | Array} dbName 数据库名
    5. * @param {String} storeName objectStore名
    6. * @param {*} key 主键
    7. */
    8. function remove(db, dbName, storeName, key) {
    9. let request = db
    10. .transaction(dbName, "readwrite") // 新建事务
    11. .objectStore(storeName) // 拿到 IDBObjectStore 对象
    12. .delete(key);
    13. request.onsuccess = (event) => {
    14. console.log("删除数据成功", event.target.result);
    15. };
    16. request.onerror = (event) => {
    17. console.log("删除数据失败", event.target.error);
    18. };
    19. request.onabort = (event) => {
    20. console.log("事务回滚", event.target);
    21. };
    22. }

    3.5 清空数据

    1. /**
    2. * 清空所有数据
    3. * @param {IDBDatabase} db 数据库实例
    4. * @param {String | Array} dbName 数据库名
    5. * @param {String} storeName objectStore名
    6. */
    7. function read(db, dbName, storeName) {
    8. let request = db
    9. .transaction(dbName, "readwrite") // 新建事务
    10. .objectStore(storeName) // 拿到 IDBObjectStore 对象
    11. .clear();
    12. request.onsuccess = (event) => {
    13. console.log("清空数据成功", event.target.result);
    14. };
    15. request.onerror = (event) => {
    16. console.log("清空数据失败", event.target.error);
    17. };
    18. request.onabort = (event) => {
    19. console.log("事务回滚", event.target);
    20. };
    21. }

    4. 游标

    1. /**
    2. * cursor 游标
    3. * @desc 指向结果集的指针
    4. * 游标工作原理:游标指针先指向结果中的第一项,在接到查找下一项的命令时,才会指向下一项。(不提前收集结果)
    5. * 创建游标:在存储空间上调用openCursor(range, direction)
    6. * @param {IDBKeyRound} range 键范围,默认范围为全部
    7. * @param {String} direction 方向
    8. * next 下一个(默认)
    9. * nextunique 下一个不重复项
    10. * prev 前一项
    11. * prevunique 前一个不重复项
    12. * @return 会返回一个请求对象,可以指定onsuccess()/onerror()事件处理程序。
    13. * onsuccess()可以通过event.target.result取得结果中的下一项。
    14. * 有下一项时:event.target.result 是 IDBCursorWithValue的实例
    15. * 无下一项时:event.target.result 是 null
    16. * 游标查找下一项指令:continue(key), advance(count)
    17. * continue(key) 移动到结果集中的下一项。参数key(主键)可选。
    18. * 不指定key,游标移动到下一项;
    19. * 指定key,游标移动到指定键。
    20. * advance(count) 向前移动count指定项数。
    21. */

     游标的使用示例,放在最后辣 ~

    5. 键范围 

    1. /**
    2. * keyRange 键范围
    3. * @desc 利用游标查找数据太局限,键范围可灵活的查找数据(实例:IDBKeyRange)
    4. * @兼容 var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
    5. * @func 四种定义键的方式,最后一种功能包含前三种
    6. * 1. only(key) // 只取得键为key的对象,类似于objectStore().get(key)
    7. * 2. lowerBound(startKey, isStartNext) // 指定游标开始的位置,默认isStartNext为false
    8. * isStartNext = false => 从startKey开始一直查找到最后
    9. * isStartNext = true => 从startKey的下一个对象开始一直查找到最后
    10. * 3. upperBound(endKey, isEndNext) // 指定游标结束的位置,默认isEndNext=false
    11. * isEndNext = false => 从头查找到endKey的位置
    12. * isEndNext = true => 从头查找到endKey的前一个对象为止
    13. * 4. bound(startKey, endKey, isStartNext, isEndNext) // 指定游标开始和结束的位置,默认isStartNext=false, isEndNext=false
    14. * isStartNext = false => 从startKey开始查找
    15. * isStartNext = true => 从startKey的下一个对象开始查找
    16. * isEndNext = false => 到endKey结束
    17. * isEndNext = true => 到endKey的上一个对象结束
    18. */

      键范围的使用示例,放在最后辣 ~

    6. 索引

    1. /**
    2. * 索引
    3. * @desc 类似对象存储空间。(为一个存储对象空间,指定多个键)
    4. * @意义 为提高查询速度而基于特定属性创建的。
    5. * 例如:通过用户id和用户名两种方式存储数据,就需要通过这两个键来存储记录。用户id作为主键,在为用户名创建索引。
    6. *
    7. * @func 创建索引 creatIndex(indexName, indexAttrName, options)
    8. * @param indexName 索引名
    9. * @param indexAttrName 索引属性名
    10. * @param options 包含unique的配置项
    11. * @return 返回IDBIndex实例
    12. *
    13. * @func 获取某个索引 index(indexName)
    14. * @param indexName 索引名
    15. * 在索引上,调用 openCursor() 来创建游标。
    16. * 此时,event.target.result.key 存储的是索引键;
    17. * event.target.result.primaryKey 存储的是主键;
    18. * event.target.result.value 存储的是整个对象。
    19. * 在索引上,调用 openKeyCursor() 来创建一个特殊的,只返回每条记录主键的游标。
    20. * 此时,event.target.result.key 存储的是索引键;
    21. * event.target.result.primaryKey 存储的是主键;
    22. * 无 event.target.result.value。
    23. * 在索引上,调用 get(indexKey) 来获取整个对象。
    24. * 此时,event.target.result 即是这个对象。
    25. * 在索引上,调用 getKey(indexKey) 来通过索引键获取主键。
    26. * 此时,event.target.result 即是这个主键。
    27. *
    28. * @func 获取某个存储空间下的所有索引 indexNames属性
    29. * @return 返回 DOMStringList 实例,即包含某个存储空间下所有索引名的对象
    30. *
    31. * @func 删除某个索引 deleteIndex(indexName)
    32. * @return 无任何返回,因为删除索引不影响存储空间,所以无任何返回。
    33. */

     索引的使用示例,放在最后辣 ~

    7. 并发问题

    1. /**
    2. * 并发问题
    3. * @desc IndexedDB提供的API是异步的,但是仍然存储并发问题。
    4. * @eg 例如:浏览器两个不同的标签打开同一页面,那么一个页面试图更新另一个页面尚未准备就绪的数据库,有可能引起并发问题
    5. * @eg 例如:把数据库设置为新版,也有可能引发并发问题(只有当浏览器仅有一个标签页打开使用数据库时,调用setVersion()才能完成)
    6. * 解决法一:每次成功打开数据库,都指定onversionchange事件处理程序。
    7. * 当同一个来源的另一个内标签页调用setVersion()时,会执行这个函数,在函数内部立即关掉数据库即可。
    8. * 关闭数据路方法:db.close()
    9. * 解决法二:调用setVersion()时,指定请求的onblocked()事件处理程序。
    10. * 当你想要更新数据库版本但另一个标签页已经打开数据库的情况下,就会触发这个事件。
    11. * 此时可通知用户关闭其他标签页,再重新调用setVersion()。
    12. */

    8. 限制

    1. /**
    2. * 限制
    3. * @desc 与Web Storage类似。
    4. * @限制1 IndexedDB只能由同源页面操作,不能跨域共享信息。
    5. * @限制2 每个数据库占用磁盘空间有限。
    6. * FireFox 4+ 的上限是每个源 50M,其他几乎都是5M
    7. * @限制3 FireFox 不允许本地文件访问IndexedDB,Chrome无限制。
    8. */

    9. 封装操作数据库的工具类

    1. /**
    2. * IndexedDB数据库操作方法类
    3. */
    4. class IDBUtils {
    5. constructor(db, dbName, store) {
    6. this.db = db; // {IDBDatabase} 已被打开的数据库
    7. this.dbName = dbName; // {String | Array} 存储空间名
    8. this.store = store; // {String} 存储空间名
    9. this.type = {
    10. success: "SUCCESS", // 操作成功
    11. error: "ERROR", // 操作失败
    12. done: "DONE", // 检索结束
    13. abort: "ABORT", // 操作回滚
    14. };
    15. }
    16. /**
    17. * 新增数据
    18. * @param {*} data 要写入的数据
    19. * @param {Function} cb 回调函数
    20. */
    21. add(data, cb) {
    22. let request = this.db
    23. .transaction(this.dbName, "readwrite") // 新建事务
    24. .objectStore(this.store) // 拿到 IDBObjectStore 对象
    25. .add(data);
    26. request.onsuccess = (event) => {
    27. if (cb) cb(this.type.success, event.target.result);
    28. };
    29. request.onerror = (event) => {
    30. if (cb) cb(this.type.error, event.target.error);
    31. };
    32. request.onabort = (event) => {
    33. if (cb) cb(this.type.abort, event.target);
    34. };
    35. }
    36. /**
    37. * 根据主键,读取数据
    38. * @param {String | Number} key 主键
    39. * @param {Function} cb 回调函数
    40. */
    41. read(key, cb) {
    42. let request = this.db
    43. .transaction(this.dbName, "readonly") // 新建事务
    44. .objectStore(this.store)
    45. .get(key);
    46. request.onsuccess = (event) => {
    47. if (cb) cb(this.type.success, event.target.result);
    48. };
    49. request.onerror = (event) => {
    50. if (cb) cb(this.type.error, event.target.error);
    51. };
    52. request.onabort = (event) => {
    53. if (cb) cb(this.type.abort, event.target);
    54. };
    55. }
    56. /**
    57. * 根据主键要么更新,要么插入
    58. * @param {*} param 一条完整的信息
    59. * @param {Function} cb 回调函数
    60. */
    61. update(param, cb) {
    62. let request = this.db
    63. .transaction(this.dbName, "readwrite")
    64. .objectStore(this.store)
    65. .put(param);
    66. request.onsuccess = (event) => {
    67. if (cb) cb(this.type.success, event.target.result);
    68. };
    69. request.onerror = (event) => {
    70. if (cb) cb(this.type.error, event.target.error);
    71. };
    72. request.onabort = (event) => {
    73. if (cb) cb(this.type.abort, event.target);
    74. };
    75. }
    76. /**
    77. * 删除数据
    78. * @param {key} key 主键
    79. * @param {Function} cb 回调函数
    80. */
    81. remove(key, cb) {
    82. let request = this.db
    83. .transaction(this.dbName, "readwrite")
    84. .objectStore(this.store)
    85. .delete(key);
    86. request.onsuccess = () => {
    87. if (cb) cb(this.type.success);
    88. };
    89. request.onerror = () => {
    90. if (cb) cb(this.type.error);
    91. };
    92. request.onabort = (event) => {
    93. if (cb) cb(this.type.abort, event.target);
    94. };
    95. }
    96. /**
    97. * 清空数据
    98. * @param {Function} cb 回调函数
    99. */
    100. clear(cb) {
    101. let request = this.db
    102. .transaction(this.dbName, "readwrite")
    103. .objectStore(this.store)
    104. .clear();
    105. request.onsuccess = () => {
    106. if (cb) cb(this.type.success);
    107. };
    108. request.onerror = (event) => {
    109. if (cb) cb(this.type.error, event.target);
    110. };
    111. request.onabort = (event) => {
    112. if (cb) cb(this.type.abort, event.target);
    113. };
    114. }
    115. /**
    116. * 关闭数据库
    117. */
    118. closeDB() {
    119. this.db.close();
    120. }
    121. /**
    122. * 删除数据库
    123. * @条件 在数据库没被打开的情况下,可以删除
    124. */
    125. deleteDB() {
    126. this.db.close();
    127. let request = window.indexedDB.deleteDatabase(this.dbName);
    128. request.onsuccess = (event) => {
    129. console.log("success", event);
    130. };
    131. request.onerror = (event) => {
    132. console.log("error", event);
    133. };
    134. }
    135. // =================================================================
    136. // ============================== 游标 ==============================
    137. // =================================================================
    138. /**
    139. * 读取全部(游标)
    140. * @param {Function} cb 回调函数
    141. */
    142. readAll(direction, cb) {
    143. let request = this.db
    144. .transaction(this.dbName)
    145. .objectStore(this.store)
    146. .openCursor(null, direction);
    147. let res = [];
    148. request.onsuccess = (event) => {
    149. let cursor = event.target.result; // 也可以在索引上打开 objectStore.index("id").openCursor()
    150. // cursor 有值,代表有下一项; cursor = null,代表没有下一项
    151. if (cursor) {
    152. res.push({ key: cursor.key, value: cursor.value });
    153. cursor.continue(); // 继续查找下一项
    154. } else {
    155. if (cb) cb(this.type.success, res);
    156. }
    157. };
    158. request.onerror = (event) => {
    159. if (cb) cb(this.type.error, event.target);
    160. };
    161. }
    162. /**
    163. * 利用游标更新 cursor.update()
    164. * @param {*} key 主键
    165. * @param {*} data 待更新数据
    166. * @param {Function} cb 回调函数
    167. */
    168. cursorUpdate(key, data, cb) {
    169. let request = this.db
    170. .transaction(this.dbName)
    171. .objectStore(this.store)
    172. .openCursor();
    173. request.onsuccess = (event) => {
    174. let cursor = event.target.result;
    175. if (cursor) {
    176. if (cursor.key === key) {
    177. let updateRequest = cursor.update(data);
    178. updateRequest.onsuccess = (event) => {
    179. if (cb) cb(this.type.success, event.target);
    180. };
    181. updateRequest.onerror = (event) => {
    182. if (cb) cb(this.type.error, event.target);
    183. };
    184. } else {
    185. cursor.continue(); // 继续查找下一项
    186. }
    187. } else {
    188. if (cb) cb(this.type.done); // 检索结束
    189. }
    190. };
    191. request.onerror = (event) => {
    192. if (cb) cb(this.type.error, event.target);
    193. };
    194. }
    195. /**
    196. * 利用游标删除 cursor.delete()
    197. * @param {*} key 主键
    198. * @param {Function} cb 回调函数
    199. */
    200. cursorDelete(key, cb) {
    201. let request = this.db
    202. .transaction(this.dbName)
    203. .objectStore(this.store)
    204. .openCursor();
    205. request.onsuccess = (event) => {
    206. let cursor = event.target.result;
    207. if (cursor) {
    208. if (cursor.key === key) {
    209. let deleteRequest = cursor.delete();
    210. deleteRequest.onsuccess = () => {
    211. if (cb) cb(this.type.success);
    212. };
    213. deleteRequest.onerror = (event) => {
    214. if (cb) cb(this.type.error, event.target);
    215. };
    216. } else {
    217. cursor.continue(); // 继续查找下一项
    218. }
    219. } else {
    220. if (cb) cb(this.type.done); // 检索结束
    221. }
    222. };
    223. request.onerror = (event) => {
    224. if (cb) cb(this.type.error, event.target);
    225. };
    226. }
    227. // ==================================================================
    228. // ============================== 键范围 =============================
    229. // ==================================================================
    230. IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange;
    231. searchOnly(key, cb) {
    232. let range = IDBKeyRange.only(key);
    233. let request = this.db
    234. .transaction(this.dbName)
    235. .objectStore(this.store)
    236. .openCursor(range);
    237. request.onsuccess = (event) => {
    238. let cursor = event.target.result;
    239. if (cursor) {
    240. if (cb) cb({ key: cursor.key, value: cursor.value });
    241. } else {
    242. if (cb) cb(this.type.done);
    243. }
    244. };
    245. request.onerror = (event) => {
    246. if (cb) cb(this.type.error, event.target.error);
    247. };
    248. }
    249. searchLowerBound(key, isNext = false, cb) {
    250. let range = IDBKeyRange.lowerBound(key, isNext);
    251. let request = this.db
    252. .transaction(this.dbName)
    253. .objectStore(this.store)
    254. .openCursor(range, "prev");
    255. let res = [];
    256. request.onsuccess = (event) => {
    257. let cursor = event.target.result;
    258. if (cursor) {
    259. res.push({ key: cursor.key, value: cursor.value });
    260. cursor.continue(); // 继续查找下一项
    261. } else {
    262. if (cb) cb(this.type.success, res);
    263. }
    264. };
    265. request.onerror = (event) => {
    266. if (cb) cb(this.type.error, event.target.error);
    267. };
    268. }
    269. searchUpperBound(key, isPre = false, cb) {
    270. let range = IDBKeyRange.upperBound(key, isPre);
    271. let request = this.db
    272. .transaction(this.dbName)
    273. .objectStore(this.store)
    274. .openCursor(range);
    275. let res = [];
    276. request.onsuccess = (event) => {
    277. let cursor = event.target.result;
    278. if (cursor) {
    279. res.push({ key: cursor.key, value: cursor.value });
    280. cursor.continue(); // 继续查找下一项
    281. } else {
    282. if (cb) cb(this.type.success, res);
    283. }
    284. };
    285. request.onerror = (event) => {
    286. if (cb) cb(this.type.error, event.target.error);
    287. };
    288. }
    289. searchBound(startKey, endKey, isNext = false, isPre = false, cb) {
    290. let range = IDBKeyRange.bound(startKey, endKey, isNext, isPre);
    291. let request = this.db
    292. .transaction(this.dbName)
    293. .objectStore(this.store)
    294. .openCursor(range);
    295. let res = [];
    296. request.onsuccess = (event) => {
    297. let cursor = event.target.result;
    298. if (cursor) {
    299. res.push({ key: cursor.key, value: cursor.value });
    300. cursor.continue(); // 继续查找下一项
    301. } else {
    302. if (cb) cb(this.type.success, res);
    303. }
    304. };
    305. request.onerror = (event) => {
    306. if (cb) cb(this.type.error, event.target.error);
    307. };
    308. }
    309. // =================================================================
    310. // ============================== 索引 ==============================
    311. // =================================================================
    312. /**
    313. * 获取存储空间对象上的索引
    314. */
    315. getIndexNames() {
    316. let indexNameList = this.db
    317. .transaction(this.dbName, "readwrite") // 新建事务
    318. .objectStore(this.store).indexNames; // 拿到 IDBObjectStore 对象
    319. console.log("indexNameList", indexNameList);
    320. }
    321. /**
    322. * 通过索引键使用游标
    323. * @param {*} indexName
    324. */
    325. getIndexCursor(indexName) {
    326. let index = this.db
    327. .transaction(this.dbName, "readwrite") // 新建事务
    328. .objectStore(this.store) // 拿到 IDBObjectStore 对象
    329. .index(indexName);
    330. let request = index.openCursor();
    331. request.onsuccess = (event) => {
    332. console.log("event", event.target.result);
    333. // 进行游标的使用、continue等逻辑
    334. };
    335. }
    336. /**
    337. * 通过索引键获取主键游标
    338. * @param {*} indexName
    339. */
    340. getIndexKeyCursor(indexName) {
    341. let index = this.db
    342. .transaction(this.dbName, "readwrite") // 新建事务
    343. .objectStore(this.store) // 拿到 IDBObjectStore 对象
    344. .index(indexName);
    345. let request = index.openKeyCursor();
    346. request.onsuccess = (event) => {
    347. console.log("event", event.target.result);
    348. // 进行游标的使用、continue等逻辑
    349. };
    350. }
    351. /**
    352. * 通过索引键获取数据
    353. * @param {*} indexName
    354. * @param {*} indexKey
    355. */
    356. formIndexGet(indexName, indexKey) {
    357. let index = this.db
    358. .transaction(this.dbName, "readwrite") // 新建事务
    359. .objectStore(this.store) // 拿到 IDBObjectStore 对象
    360. .index(indexName);
    361. let request = index.get(indexKey);
    362. request.onsuccess = (event) => {
    363. console.log("event", event.target.result);
    364. };
    365. }
    366. /**
    367. * 通过索引键获取主键
    368. * @param {*} indexName
    369. * @param {*} indexKey
    370. */
    371. fromIndexGetKey(indexName, indexKey) {
    372. let index = this.db
    373. .transaction(this.dbName, "readwrite") // 新建事务
    374. .objectStore(this.store) // 拿到 IDBObjectStore 对象
    375. .index(indexName);
    376. let request = index.getKey(indexKey);
    377. request.onsuccess = (event) => {
    378. console.log("event", event.target.result);
    379. };
    380. }
    381. }

    索引、游标、键范围的基本使用如上,当然还可以利用 索引+游标+键范围来查询数据,大家有需要可以自己封装

  • 相关阅读:
    java计算机毕业设计高校宿舍管理系统演示视频2021源码+mysql数据库+系统+lw文档+部署
    Python3中用户注册小案例 - 解决中文字符问题 (代码)
    2022-08-10 学习日记(30th day)注解
    计算机网络第1章 (概述)
    Mybatis中表之间的关联关系
    解释pom中的依赖dependency
    【算法小记】深度学习——时间序列数据分析 Time series Data Analysis
    cnpm install时,报错TypeError: randomUUID is not a function无法初始化
    【李沐深度学习笔记】矩阵计算(2)
    如何设置Linux的语言环境
  • 原文地址:https://blog.csdn.net/weixin_44137575/article/details/128024783