IndexedDB 中文教程

IndexedDB 中文教程

本文通过对IndexedDB的概念、API进行详解,讲清楚IndexedDB中的事务机制,以及objectStore这个核心概念。和一般的教程不同,这篇文章除了一步一步搭建起一个IndexedDB数据库操作的流程,连接、选择、读取、更新等,而且还把最常用的API接口列举出来,方便开发者在一个地方就可以完成所有查询。

前言

indexedDB 是 html5 标准【本文受版权保护】转载请注明出处:www.tangshuang.net引入的web数据持久化方案之一,现代浏览【未经授权禁止转载】【未经授权禁止转载】器大多按照标准对其进行了实现,我在新的项【作者:唐霜】本文作者:唐霜,转载请注明出处。目中用到它来作为持久化数据存储,于是详细本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net研究了一番,MDN 上的解释虽然权威,但【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net是由于知识不成体系,细节也讲的不透,所以未经授权,禁止复制转载。未经授权,禁止复制转载。我打算自己写一篇教程,对 indexed【原创内容,转载请注明出处】【版权所有,侵权必究】DB 的各个细节进行详解。

原创内容,盗版必究。【本文首发于唐霜的博客】

IndexedDB 在线视频教程,7个课【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。时让你精通 indexedDB 的操作和本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。理解底层标准设计,助你在前端开发中游刃有转载请注明出处:www.tangshuang.net【未经授权禁止转载】余地使用数据存储

未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。
转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。

为了和读者更贴近,我做了上面这套视频教程,总共7个课时,每天一小时,7天可学完。【版权所有,侵权必究】转载请注明出处:www.tangshuang.net虽然本文的内容已经覆盖了所有与 inde【转载请注明来源】本文作者:唐霜,转载请注明出处。xedDB 相关的内容,但是视频教程的方原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】式更轻松,而且其中有关概念的部分讲解的更转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。详细。掌握一门技术,不需要很长时间,7天【原创不易,请尊重版权】原创内容,盗版必究。就可以。视频教程是付费教程,价格不贵,写转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。教程真的不容易,希望大家多支持。

【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。【转载请注明来源】

架构体系

这里说的结构体系,是指在 indexed著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】DB 中,几个重要的概念之间的关系。这些【关注微信公众号:wwwtangshuangnet】【访问 www.tangshuang.net 获取更多精彩内容】概念包括:

【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】

简单的说,indexedDB 是非关系型【作者:唐霜】【版权所有】唐霜 www.tangshuang.net数据库,数据组织不像 SQL 数据库一样转载请注明出处:www.tangshuang.net【未经授权禁止转载】,有表和字段,indexedDB 里面没本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】有表和字段的概念,它的最小组织单位(un【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】it)是 key-value。在 ind【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。exedDB 里,一对 key-valu本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。e 就相当于 SQL 数据库里面的一条记未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】录,是数据的最终体现形式。我们通过下面的原创内容,盗版必究。【本文受版权保护】图来阐述 indexedDB 和 SQL本文作者:唐霜,转载请注明出处。【本文受版权保护】 数据库结构体系的不同,以帮助理解。

著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。

转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。【未经授权禁止转载】【作者:唐霜】

关系型数据库和非关系型数据库本身有非常大【版权所有】唐霜 www.tangshuang.net【本文受版权保护】的差别,关系型数据库大致上架构是一致的,【作者:唐霜】【本文受版权保护】但是非关系型数据库的架构各式各样,很不统【版权所有,侵权必究】【本文受版权保护】一。就 SQL DB 和 indexed【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】DB 而言:

转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。

indexedDB 中的 objectS【原创不易,请尊重版权】转载请注明出处:www.tangshuang.nettore 虽然和 SQL DB 中的 t本文作者:唐霜,转载请注明出处。【本文受版权保护】able 非常像,但是它们的存储形式却极【作者:唐霜】【未经授权禁止转载】其不同。objectStore 比 ta【作者:唐霜】【转载请注明来源】ble 简单的多。

原创内容,盗版必究。【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】

同时,indexedDB 内置了事务系统【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net,所有读写操作都是在事务中完成。

【作者:唐霜】【版权所有,侵权必究】转载请注明出处:www.tangshuang.net

数据库

indexedDB 是一个完备模型的数据【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。库,有标准的数据库结构体系。它虽然不是一转载请注明出处:www.tangshuang.net【本文受版权保护】个运行时服务,而是基于文件的即时存取数据【作者:唐霜】【版权所有】唐霜 www.tangshuang.net库,但是仍然可以用其他数据库的模型思维来【本文首发于唐霜的博客】【本文受版权保护】了解它。在 indexedDB 中,我们未经授权,禁止复制转载。【未经授权禁止转载】可以创建多个数据库,每个数据库有自己独立【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。的空间。

本文作者:唐霜,转载请注明出处。【转载请注明来源】原创内容,盗版必究。【本文首发于唐霜的博客】

连接数据库

要在 indexedDB 中存储数据,要原创内容,盗版必究。【未经授权禁止转载】进行两步操作,第一步连接到某个数据库,第【原创不易,请尊重版权】【原创不易,请尊重版权】二步挑选某个 objectStore 进本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】行数据操作。现在讲解连接到 indexe【本文受版权保护】【本文首发于唐霜的博客】dDB 数据库。在 window 对象上【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。有一个 indexedDB 对象,直接调本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】用 open 方法进行打开,如果该数据库【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net不存在,则创建一个新的数据打开:

原创内容,盗版必究。本文作者:唐霜,转载请注明出处。
const request = window.indexedDB.open('mydb', 1)

open有两个参数:

未经授权,禁止复制转载。【本文受版权保护】【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】

数据库版本

上面的version参数对于初学者而言不本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net是很好理解。如果你用过 docker 的【作者:唐霜】转载请注明出处:www.tangshuang.net话,知道有一个东西叫镜像(image),本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。在镜像的基础上构建自己的容器,可以再创建转载请注明出处:www.tangshuang.net【本文受版权保护】一个新的镜像,那么这个新的镜像其实就包含本文版权归作者所有,未经授权不得转载。【本文受版权保护】了老的镜像。这里的 version 也类【本文受版权保护】【原创内容,转载请注明出处】似,它表示当前的数据库结构的版本。ver【本文受版权保护】未经授权,禁止复制转载。sion 必须是正整数,只能升不能将,只本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。有当需要进行数据库结构修改的时候,才需要【未经授权禁止转载】未经授权,禁止复制转载。升级 version。

著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net

例如,一开始,version 为 1,创【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】建了一些 objectStore,当你需【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。要添加新的 objectStore 或者原创内容,盗版必究。【未经授权禁止转载】修改某些 objectStore 的时候本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。,就需要升级 version。一个数据库未经授权,禁止复制转载。【转载请注明来源】只能在同一时间存在一个 version,著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】不能同时存在多个 version。当你的【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.net version 升级之后,你还用老的 转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】version 去连接数据库,并进行数据本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。操作时,会抛出错误。

【本文受版权保护】【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。

补充:有同学留言想对这个问题进行深入探讨【本文首发于唐霜的博客】【原创内容,转载请注明出处】。我这里说一下我的想法。从项目的开发上讲著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】,我们只会在发布代码时去升级 versi【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】on,而不会在程序运行过程中通过程序去更未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】改 version,因为一旦用户刷新页面本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】,这个 version 会变成代码中设置【转载请注明来源】【原创内容,转载请注明出处】的 version,这会造成错误。我们升转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】级 version,是为了对数据库结构进著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】行修改,触发 onupgradeneeded 方法。

【版权所有,侵权必究】【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。

在MDN里面有这样一句话:When you call open()【作者:唐霜】【版权所有】唐霜 www.tangshuang.net with a greater vers【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】ion than the actual 本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。version of the datab本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。ase, all other open 未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】databases must expli【本文受版权保护】本文作者:唐霜,转载请注明出处。citly acknowledge th【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。e request before you【本文受版权保护】【版权所有】唐霜 www.tangshuang.net can start making ch【转载请注明来源】【本文受版权保护】anges to the databas本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。e (an onblocked even【版权所有】唐霜 www.tangshuang.net【转载请注明来源】t is fired until the【版权所有,侵权必究】【本文受版权保护】y are closed or relo【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】aded). 也就是说,1. 你要传入一个更大当版本本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】来触发 onupgradeneeded,【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】2. 在数据库处于 open 状态时,对转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】数据库对修改是被 block 住,直到它【版权所有,侵权必究】【原创不易,请尊重版权】被 close 或 reload 之后,【原创内容,转载请注明出处】未经授权,禁止复制转载。这些修改才会生效。

【未经授权禁止转载】【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】
【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。

现在你需要记住的是,在后面的代码操作中,著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net你要时刻保证你使用对了 version,本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。它的使用场景只有两种:

【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。

从代码的层面来看,并非这两个事情发生才触【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】发了 version 的改变,恰恰相反,【转载请注明来源】【作者:唐霜】如果你要修改或添加 objectStor未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。e,你必须通过传递新的 version 转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】参数到 open 方法中,触发 onupgradeneeded,在 on【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】upgradeneeded 的回调函数中【作者:唐霜】【未经授权禁止转载】才能实现目的。

【版权所有,侵权必究】【本文首发于唐霜的博客】【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。

获得 db 容器

怎么从上面的 open 方法之后,获得可未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。以用来进行操作的数据库对象容器:

未经授权,禁止复制转载。原创内容,盗版必究。原创内容,盗版必究。
const request = window.indexedDB.open('mydb', 1)
request.onsuccess = e => {
  const db = e.target.result
}

这样就获得了db的容器,利用该容器,我们【转载请注明来源】【版权所有,侵权必究】就可以进行数据库的下一步操作。

著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】

这是一个异步的操作,你不能在上面代码之后著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。直接使用 db 变量,而是要在 onsu【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。ccess 的函数体内继续写代码。而且 【本文首发于唐霜的博客】未经授权,禁止复制转载。indexedDB 的所有编程都是这样,著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。这会导致嵌套层层加深,因此,我们这篇文章【原创不易,请尊重版权】【本文受版权保护】后面还会提供使用 Promise 进行封【版权所有】唐霜 www.tangshuang.net【转载请注明来源】装的类,使用该类你无需做复杂的操作。

【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net

objectStore

objectStore 是 indexe著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】dDB 中非常核心的概念,它是数据的存储【作者:唐霜】【本文首发于唐霜的博客】仓库,一个 objectStore 类似原创内容,盗版必究。未经授权,禁止复制转载。于 SQL 数据库中的表,存放着相关的所【本文首发于唐霜的博客】【作者:唐霜】有数据记录。

【版权所有】唐霜 www.tangshuang.net【本文受版权保护】转载请注明出处:www.tangshuang.net

什么是 objectStore?

indexedDB 是 key-valu【原创不易,请尊重版权】【原创不易,请尊重版权】e 数据库,具体体现就是 objectS本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.nettore. objectStore 是 【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。indexedDB 的数据存储机制,和 【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。SQL 的表的地位一致。每一条记录包含了【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。 key 和 value。

未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】【版权所有,侵权必究】

【原创内容,转载请注明出处】【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】

indexedDB 之所以将自己的存储机本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。制称为 objectStore,在 st转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】ore 前面加上 object,是因为它【本文受版权保护】本文版权归作者所有,未经授权不得转载。所存储的记录的集合,就像一个 objec【版权所有,侵权必究】【未经授权禁止转载】t 一样,是一个 key-value 的【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net集合。

【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】

什么是 key?

key 是 value 的标记值。

【转载请注明来源】本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。

我们通过 key 得到 indexedD【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.netB 中存储的对应值。要获得 value,未经授权,禁止复制转载。【本文首发于唐霜的博客】必须通过 key 来获得。key 和 v【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】alue 具有绑定关系,key 相当于 未经授权,禁止复制转载。原创内容,盗版必究。value 的缩写、别名、标记。

【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。

但和 localStorage 不同,i【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.netndexedDB 的 key 有两种形态本文作者:唐霜,转载请注明出处。原创内容,盗版必究。:inline 和 outline。in著作权归作者所有,禁止商业用途转载。【转载请注明来源】line key 是指 key 被包含在本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】 value 中,例如你存储的 valu原创内容,盗版必究。本文作者:唐霜,转载请注明出处。e 是对象时,就可以将 key 包含在 【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】value 中。outline key 【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net则是不被包含在 value 中,例如你存原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net储的是字符串,或者 ArrayBuffe原创内容,盗版必究。【版权所有,侵权必究】r,就不可能在 value 中包含 ke原创内容,盗版必究。转载请注明出处:www.tangshuang.nety,这种情况下通过开启 autoIncr原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】ement 来实现,下文会详细介绍。

【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。

【转载请注明来源】著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】

上图中上面一条记录的 value 是一个【本文受版权保护】本文作者:唐霜,转载请注明出处。对象,key 来自对象的 id 属性值,转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net这个 key 是 inline key。【本文受版权保护】【转载请注明来源】下面一条记录,value 是一个字符串,未经授权,禁止复制转载。转载请注明出处:www.tangshuang.netkey 是由系统自动生成,这个 key 本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】是 outline key。

【本文首发于唐霜的博客】【本文受版权保护】原创内容,盗版必究。

例如有一个值是 { body: { color: 'red' } } 而 keyPath 为 body.color,那么就可以得到 key 为 red。这可能和我们以前理解的地方有所不同。在【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】 IndexedDB 中,我们要通过 r本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】ed 去找到这个值。

原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】

什么是 keyPath?

keyPath 是指在对象中,获取一个节著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】点值的属性链式方法的字符串表达。例如:

【转载请注明来源】未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】
{
  books: [
    { name: 'My Uncle Tom', price: 13.4 }
  ],
}

其中我要获得第一本书的价格,那么它的 k【未经授权禁止转载】【作者:唐霜】eyPath 就是 ‘boo未经授权,禁止复制转载。【版权所有,侵权必究】ks[0].price’。它【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。是一个字符串,但可以用来表达获得一个节点【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】值的属性路径。所以,keyPath 这个著作权归作者所有,禁止商业用途转载。【转载请注明来源】单词中的 path 就是这个意思。

【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。【作者:唐霜】

key 和 keyPath 的联系

keyPath 的作用是读取 key。

原创内容,盗版必究。【作者:唐霜】著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。

key 是 value 的 keyPat【本文受版权保护】【关注微信公众号:wwwtangshuangnet】h 的值。

【作者:唐霜】本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。原创内容,盗版必究。
【原创内容,转载请注明出处】未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。【未经授权禁止转载】

这句话的意思是:1. value 是一个【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】对象,2. 以 keyPath 作为属性著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net路径从 value 中读取某个节点的值;本文版权归作者所有,未经授权不得转载。【转载请注明来源】3. 这个值就是 key。当然,这里面有【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】一些前提条件,例如“value 是一个对【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net象”,不是字符串,“value 存在 k【关注微信公众号:wwwtangshuangnet】【原创内容,转载请注明出处】eyPath,并能读取值”。

【作者:唐霜】【作者:唐霜】

一般而言,keyPath 在创建 obj转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。ectStore 和 index 的时候未经授权,禁止复制转载。【原创不易,请尊重版权】就已经确定了,不会改。所以,在实际编程的【关注微信公众号:wwwtangshuangnet】【转载请注明来源】时候,我们很少会去用 keyPath,而本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。是拿到一个 key 进行操作。

【原创不易,请尊重版权】【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net

keyPath 的高级用法是,支持一个数本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net组作为 keyPath,但这个我们不深入本文作者:唐霜,转载请注明出处。【转载请注明来源】探讨。如果 keyPath 是一个数组,【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。表示在查询的时候,只要其中之一可以查到值转载请注明出处:www.tangshuang.net原创内容,盗版必究。,就返回得到的值。

著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】

对于 outline key 的情况,在【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。创建 objectStore 时,我们不【本文首发于唐霜的博客】【版权所有,侵权必究】能传 keyPath,并且开启 auto【作者:唐霜】本文版权归作者所有,未经授权不得转载。Increment,indexedDB 【本文受版权保护】原创内容,盗版必究。会默认以 ‘id’【作者:唐霜】【转载请注明来源】; 作为 keyPath,但我们不会用到原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。这个 ‘id’。

【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net

可以存储哪些数据类型?

根据 w3c 文档描述,indexedDB 可以存储的数据类型本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】为:

未经授权,禁止复制转载。未经授权,禁止复制转载。

String, Date, Object【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。, Arra, FileBlobImageData等等。另外,网上很多人指出,支持存储 A【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.netrrayBuffer。

著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】

根据 w3c 的描述,凡是能进行序列化的未经授权,禁止复制转载。【未经授权禁止转载】值,都可以被 indexedDB 存储。原创内容,盗版必究。原创内容,盗版必究。也就是说,不能被序列化的,例如自引用的 著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。object,或者某些类的实例,还有 f【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】unction,就不能被 indexed本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】DB 存储。简单理解就是,不能存func未经授权,禁止复制转载。【转载请注明来源】tion等非结构化的数据,object必未经授权,禁止复制转载。【本文受版权保护】须是以键值对组成的字面对象。

【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】

创建 objectStore

创建 objectStore 和修改 o本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.netbjectStore 都只能在 db 的 onupgradeneeded 事件中进【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】行,因此,要创建 objectStore【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】,必须在前面的 open 操作那个时候来【转载请注明来源】【本文首发于唐霜的博客】进行。

【未经授权禁止转载】【本文受版权保护】著作权归作者所有,禁止商业用途转载。
const request = window.indexedDB.open('mydb', 1)
request.onupgradeneeded = (e) => {
  const db = e.target.result
  db.createObjectStore('mystore', { keyPath: 'id' })
}
request.onsuccess = (e) => {
  const db = e.target.result
  // ...
}

上面的红色代码中,我们使用 create未经授权,禁止复制转载。【本文首发于唐霜的博客】ObjectStore 方法来实现 ob【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。jectStore 的创建。但是,需要注【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。意的是,一个 database 中,只允【作者:唐霜】【版权所有】唐霜 www.tangshuang.net许存在一个同名的 objectStore【未经授权禁止转载】原创内容,盗版必究。,因此,如果你第二次 createObj转载请注明出处:www.tangshuang.net【本文受版权保护】ectStore 相同名的objectS【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】tore,程序会报错。比如你的程序如果像未经授权,禁止复制转载。【原创内容,转载请注明出处】上面这样写,必然会遇到一个问题,就是当你【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。更新 version 的时候,会再次执行【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。 createObjectStore,那【转载请注明来源】【转载请注明来源】么就会报错,程序就会中断。另一个注意点是本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】,一旦一个 objectStore 被创【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。建,它的 name 和 keyPath 转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net是不能修改的。那么有什么办法来控制呢?通【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.net过一个判断,判断是否已经存在同名的 ob【未经授权禁止转载】【本文受版权保护】jectStore 即可。

转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net
const request = window.indexedDB.open('mydb', 1)
request.onupgradeneeded = (e) => {
  const db = e.target.result
  if (!db.objectStoreNames.contains('mystore')) {
    db.createObjectStore('mystore', { keyPath: 'id' })
  }
}
request.onsuccess = (e) => {
  const db = e.target.result
  // ...
}

onupgradeneeded 不会在每【未经授权禁止转载】【转载请注明来源】次刷新页面的时候执行,而是在刷新页面时,本文版权归作者所有,未经授权不得转载。【作者:唐霜】indexedDB 发现 version【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。 被升级了的时候执行。因此,所有的数据库未经授权,禁止复制转载。原创内容,盗版必究。结构的东西,都要放在这个函数内去做。

【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。

objectStore 创建之后不可修改【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】,如果创建时失误,给了错误的配置,必须先本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。删除该 objectStore 之后,重本文作者:唐霜,转载请注明出处。【未经授权禁止转载】新创建。

【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】

objectStore 的类型

在编程上,不需要去分 objectSto【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。re 的类型。但是,在我们实际存储数据的原创内容,盗版必究。【原创不易,请尊重版权】时候,我们自己需要去区分,因为不同类型的【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net objectStore 用法不同。

【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】

对象型仓库

如果一个 objectStore 是用来本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】存对象的,那么这种情况下你应该每次都存入转载请注明出处:www.tangshuang.net【作者:唐霜】一个对象,而且,这个对象有一个属性路径是【转载请注明来源】【未经授权禁止转载】规定的 keyPath。倘若这个对象不存本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。在对应的 keyPath,那么就会报错。

【未经授权禁止转载】未经授权,禁止复制转载。【作者:唐霜】本文作者:唐霜,转载请注明出处。

这里的对象不包括数组。

转载请注明出处:www.tangshuang.net【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】
db.createObjectStore('mystore', { keyPath: 'id' })

非对象型仓库

如果一个 objectStore 是用来【作者:唐霜】【本文受版权保护】存非对象的,例如我们经常会考虑用来存 A【原创不易,请尊重版权】【原创内容,转载请注明出处】rrayBuffer,这个时候,你应该在【本文受版权保护】【转载请注明来源】创建 objectStore 的时候,传著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。入配置信息 autoIncrement 本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。为 true,不传 keyPath。

著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。
db.createObjectStore('mystore', { autoIncrement: true })

这种情况下,存入数据(ArrayBuff著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。er)时,key 会被自动添加上,且跟 【本文受版权保护】【原创不易,请尊重版权】SQL 数据的自增字段一样,索引值会在原【转载请注明来源】未经授权,禁止复制转载。有基础上自加 1。在查询或更新值的时候,【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】都要使用这个值作为 key。但是,这种情【版权所有,侵权必究】未经授权,禁止复制转载。况下,会有一个问题,key 是在运行时保【作者:唐霜】【未经授权禁止转载】存在内存中的,一旦用户刷新页面,你就不知【访问 www.tangshuang.net 获取更多精彩内容】【转载请注明来源】道刚刚插入的值的 key 了。对于这种情未经授权,禁止复制转载。【未经授权禁止转载】况,如果想持久化,可以和 localSt【原创内容,转载请注明出处】【原创内容,转载请注明出处】orage 一起使用来解决。

转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。

混合仓库

如果你硬是要在一个 objectStor本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】e 中混合存值,那么必须按照非对象型仓库【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。来使用。但是会有一个不一样的地方,当你存【本文受版权保护】本文作者:唐霜,转载请注明出处。入一个对象时,如果该对象中并没有对应的 【转载请注明来源】【本文受版权保护】keyPath,那么,它会在存入时被自动【本文首发于唐霜的博客】【原创内容,转载请注明出处】加上这个 keyPath。这一点非常奇怪本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。,你会发现,存入 string, Blo原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.netb 和存入 object 的效果竟然不同【本文受版权保护】原创内容,盗版必究。

【转载请注明来源】【未经授权禁止转载】【转载请注明来源】
db.createObjectStore('mystore', { keyPath: 'id', autoIncrement: true })

当你插入的对象中不存在 id 属性时,对著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】象会被污染,会自动加上 id 属性,并且原创内容,盗版必究。【本文受版权保护】赋予一个数字作为 key。

【原创不易,请尊重版权】【版权所有,侵权必究】【作者:唐霜】

什么是 autoIncrement?

前面提到过 autoIncrement,未经授权,禁止复制转载。原创内容,盗版必究。但是没有详细解释。这需要涉及到一个叫 key generator 的东西,但是它过于底层,我们这里不深入【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net讲解,你可以自行了解,我们这里做简化说明【本文受版权保护】【未经授权禁止转载】。autoIncrement 是一个配置原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net。当创建 objectStore 时,如【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】果 autoIncrement 被设置为【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net true,那么它的 key 将具备自动【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。生成的能力。

【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】【转载请注明来源】未经授权,禁止复制转载。

什么是自动生成?

著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。

对于对象型仓库,如果新增的值不存在对应的【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】 key,那么被存的值会被“污染”。标准原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net文档中是这么说的:“Then the v【本文受版权保护】【转载请注明来源】alue provided by the本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】 key generator is us【版权所有,侵权必究】【原创内容,转载请注明出处】ed to populate the k【本文受版权保护】本文版权归作者所有,未经授权不得转载。ey value.”也就是说,你在取出这未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。个值的时候,这个 key 被添加到了值上未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net,也就是说,存入的值被改了(添加了属性)【原创内容,转载请注明出处】【本文受版权保护】

【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。

对于我们开发者而言,一般的建议是,如果你【作者:唐霜】原创内容,盗版必究。的 objectStore 用于存储对象未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】,尽量不要开启 autoIncremen【原创不易,请尊重版权】【本文首发于唐霜的博客】t 功能。只有在储存非对象值时,一定要开著作权归作者所有,禁止商业用途转载。【本文受版权保护】启 autoIncrement 功能。不【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net建议使用混合型仓库。

【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net

index

索引是 indexedDB 中最值得玩味【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】的部分,这也是它取名“indexedDB【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。”的原因。索引,是一系列概念的统称:

【转载请注明来源】著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】

简单的说,索引是独立于 objectSt【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。ore 之外,但又和 objectSto【本文受版权保护】转载请注明出处:www.tangshuang.netre 绑定的,用于建立更多查询线索的工具【转载请注明来源】转载请注明出处:www.tangshuang.net

【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】

什么是 index?

本质上,一个 index 是一个特殊的 著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。objectStore,它的存储结构和 【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】objectStore 基本一致,也有自【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。己的 name(本文标记为 indexN转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。ame), keyPath, key 和【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。 value。特殊之处在于,索引的 ke【原创不易,请尊重版权】【本文首发于唐霜的博客】y 具有一定的逻辑约束,例如 uniqu【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.nete 用于规定该 key 是唯一的。

【原创内容,转载请注明出处】【本文受版权保护】

【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】

上图是一个 index 存储器的示意图,【原创不易,请尊重版权】未经授权,禁止复制转载。一个 objectStore 可以有多个本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】 index 和自己绑定。

著作权归作者所有,禁止商业用途转载。【作者:唐霜】

index 和 objectStore 的关系

index 依附于 objectStor转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。e。我们在创建索引时,首先要得到一个 o【转载请注明来源】【转载请注明来源】bjectStore,再在这个 obje【版权所有,侵权必究】转载请注明出处:www.tangshuang.netctStore 的基础上创建一个索引。一未经授权,禁止复制转载。【原创不易,请尊重版权】个 objectStore 可以有多个索【原创内容,转载请注明出处】【未经授权禁止转载】引。

【原创不易,请尊重版权】【原创内容,转载请注明出处】【本文受版权保护】

index 的 key 和 value 本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】全部来自 objectStore。key原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】 为某条记录的 keyPath(inde本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.netx.keyPath)的值,value 为【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。这条记录的 key(objectStor本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。e.key)。index 中的一条记录自【转载请注明来源】【作者:唐霜】动和 objectStore 中的对应记【本文受版权保护】著作权归作者所有,禁止商业用途转载。录绑定,当 objectStore 中的【未经授权禁止转载】本文作者:唐霜,转载请注明出处。记录发生变化时,index 中的记录会自【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net动被污染(自动更新)。

【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。

转载请注明出处:www.tangshuang.net【本文受版权保护】

index 实际上是对 objectSt【作者:唐霜】本文版权归作者所有,未经授权不得转载。ore 查询条件的补充。如果没有 ind著作权归作者所有,禁止商业用途转载。【本文受版权保护】ex,我们只能通过 objectStor未经授权,禁止复制转载。【作者:唐霜】e 的 key 来查值,但是有了 ind本文版权归作者所有,未经授权不得转载。【本文受版权保护】ex,我们可以查询的能力被扩展到了任意属本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。性路径。

原创内容,盗版必究。未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。

和 objectStore 不同,ind转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.netex 的同一个 key 可以存在多个,因【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。为不同的存入值的某个 keyPath 可本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】能存在相同的值。

著作权归作者所有,禁止商业用途转载。【作者:唐霜】【原创内容,转载请注明出处】

如何创建索引?

创建索引这个动作,实际上是对 objec【关注微信公众号:wwwtangshuangnet】【转载请注明来源】tStore 进行修改,因此,只能在 d原创内容,盗版必究。转载请注明出处:www.tangshuang.netb 的 onupgradeneeded 事件中处著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】理。

原创内容,盗版必究。【本文首发于唐霜的博客】【版权所有,侵权必究】
let request = window.indexedDB.open('mydb', 1)
request.onupgradeneeded = e => {
  let db = e.target.result
  let objectStore = db.createObjectStore('mystore', { keyPath: 'id' }) //注意这里应该进行判断是否已经存在这个 objectStore,我是为了省事
  objectStore.createIndex('price', 'book.price', { unique: false })
}

objectStore 对象有一个 cr【转载请注明来源】【本文受版权保护】eateIndex 方法,它可以创建索引【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】。它有三个参数,第一个参数是这个索引的 著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】indexName,第二个参数是 key未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.netPath,第三个参数是 options,原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。其中 unique 选项被放在这里面。

本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】

如何修改索引?

虽然 objectStore 本身的信息本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。是不能修改的,比如 name 和 key原创内容,盗版必究。未经授权,禁止复制转载。Path 都是不能修改的,但是它所拥有的转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net索引可以被修改,修改其实就是删除+添加操【关注微信公众号:wwwtangshuangnet】【访问 www.tangshuang.net 获取更多精彩内容】作。用到的就是 deleteIndex 【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】这个方法,所以,如果你想修改一个索引,要【原创不易,请尊重版权】【转载请注明来源】做的就是先删除掉原来的同名索引,然后添加【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。新的索引。举个例子,如果你知道数据库中已【作者:唐霜】原创内容,盗版必究。经存在 mystore 这个 objec【转载请注明来源】本文作者:唐霜,转载请注明出处。tStore 了:

本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】
request.onupgradeneeded = (e) => {
  const objectStore = e.target.transaction.objectStore('mystore')
  const indexNames = objectStore.indexNames
  if (indexNames.contains('name')) {
    objectStore.deleteIndex('name')
  }
  objectStore.createIndex('name', 'name', { unique: false })
}

上面这段代码通过对已有的 objectS【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】tore 的 index 进行操作,如果【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。存在某个 index 时,就删除它再添加本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】,如果没有就直接添加。

转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】【转载请注明来源】原创内容,盗版必究。

索引的运行机制

indexName 是对一个索引的命名,【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】这个名字会被用在按索引检索中,它本身和使【版权所有,侵权必究】未经授权,禁止复制转载。用被存储数据的那个属性路径没关系,但你可【版权所有,侵权必究】【本文首发于唐霜的博客】以把它当做是一个别名。

【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】【转载请注明来源】

例如,你在创建索引的时候,是这样创建的:

未经授权,禁止复制转载。【本文受版权保护】著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】
objectStore.createIndex('indexName', 'index.keyPath', { unique: false })

在根据索引进行查询的时候,语法是这样的:

本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】【转载请注明来源】【关注微信公众号:wwwtangshuangnet】
const request = objectStore.index('indexName').get('indexKey')

这实际上是两个过程,第一个过程是在保存数【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net据时(包括创建和更新),索引区会同步更新著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】自己的 key,它包含如下步骤:

【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net

第二个过程是查询过程,.index('indexName') 这个动作就是从名字为 indexNam未经授权,禁止复制转载。【转载请注明来源】e 的索引区去进行索引查询,.get('indexKey') 这个动作包含了好几步:

本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】

从某种意义上讲,索引查询的性能肯定不如直【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net接通过 objectStore 的 ke原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。y 查询。

本文作者:唐霜,转载请注明出处。【本文受版权保护】【版权所有,侵权必究】

[1] 在索引中,存在一个叫 referenced value 的东西,即一个索引建立的时候,会自动引转载请注明出处:www.tangshuang.net【本文受版权保护】用 objectStore 中对应的记录本文作者:唐霜,转载请注明出处。【本文受版权保护】。所以,对于开发者,不用担心索引是如何去转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】快速找到它在 objectStore 的【版权所有,侵权必究】未经授权,禁止复制转载。对应记录的。

转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。原创内容,盗版必究。

什么是 unique?

默认情况下,index 的 key 是可【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】以重复的。所有的值被存在 objectS【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】tore 中,但是所有值除了 objec【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】tStore 中规定的 keyPath 原创内容,盗版必究。【原创内容,转载请注明出处】必须唯一之外,默认情况下,其他属性可以相本文作者:唐霜,转载请注明出处。【转载请注明来源】同。但是,如果你建立的索引传入了 uni本文作者:唐霜,转载请注明出处。原创内容,盗版必究。que 参数,那么情况就会发生变化。也就本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。是说,该索引的 keyPath 被用于检【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。查存入的值对应的 keyPath 是否已【未经授权禁止转载】【本文受版权保护】经有值,如果 objectStore 中【本文受版权保护】【未经授权禁止转载】存在该 keyPath 的值为将要存入的【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。值的该 keyPath 值,那么会抛出错著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】误。

本文作者:唐霜,转载请注明出处。原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】

transaction

所有结构完备的数据库中都有“事务”这个概【本文受版权保护】原创内容,盗版必究。念,它是为了确保当并非执行某些操作时,不著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】致混乱。举个简单的例子,当你在像好友打钱【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。的时候,发起了一个请求,这个请求发起后,未经授权,禁止复制转载。【原创内容,转载请注明出处】就建立了你打钱的事务,后面一大堆数据库写【版权所有,侵权必究】【作者:唐霜】入的操作,但是,假如中间突然机房停电,银【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】行系统发生故障,你又发起了第二个打钱的请【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net求,那么会不会有这样一种可能,你第一次打【本文首发于唐霜的博客】【转载请注明来源】出去的钱你朋友根本没收到?数据库系统为了原创内容,盗版必究。转载请注明出处:www.tangshuang.net避免这种情况,采用事务机制,如果出错,那【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net就回滚,把你打出去但对方没收到的钱回到你【原创不易,请尊重版权】原创内容,盗版必究。账上,重新再执行一次打钱的操作,执行完这著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】个操作之后,再执行你第二次打钱的操作。这未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。样就保证了数据库增删改有序不混乱。

【关注微信公众号:wwwtangshuangnet】本文作者:唐霜,转载请注明出处。

什么是 transaction?

indexedDB 里面的事务,保证了所著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。有操作(特别是写入操作)是按照一定的顺序转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net进行,不会导致同时写入的问题。另外,in【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】dexedDB 里面,强制规定了,任何读【原创内容,转载请注明出处】未经授权,禁止复制转载。写操作,都必须在一个事务中进行。从前面的【转载请注明来源】【原创不易,请尊重版权】代码里面你也看到了,对 objectSt本文作者:唐霜,转载请注明出处。【本文受版权保护】ore 的修改,其实也是在一个事务中进行著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net

【作者:唐霜】【关注微信公众号:wwwtangshuangnet】

特别是写操作,事务通过尝试性写入完成第一【未经授权禁止转载】【本文首发于唐霜的博客】步更新,如果整个尝试过程没有出错,那么会【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】通过一个 commit 操作使得整个更新【本文受版权保护】【本文受版权保护】生效。但是如果在尝试过程中出错了,就会进【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。行一个 abort 操作,之前做过的尝试【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。会直接被丢弃,数据不会发生改变。一个 o【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。bjectStore 的写入过程中,另外本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net一个写入操作会被挂起,直到上一个事务完成【转载请注明来源】转载请注明出处:www.tangshuang.net

【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。【作者:唐霜】【本文受版权保护】

如何使用 transaction?

在代码层面,我们必须通过 transac著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。tion 方法,向数据库容器提出事务要求著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。,才能往具体的 objectStore 【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。进行数据处理:

原创内容,盗版必究。【版权所有,侵权必究】【本文受版权保护】
let transaction = db.transaction(['myObjectStore'], 'readonly')
let objectStore = transaction.objectStore('myObjectStore')
let request = objectStore.get('111')

上面这段代码的操作,我们得到了具体要进行本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net操作的 objectStore,这和我们本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。预期直接通过 db.objectStore('myObjectStore') 这样简洁的方法完全不同,indexed未经授权,禁止复制转载。转载请注明出处:www.tangshuang.netDB 中不能这么直接去获取 object【作者:唐霜】本文版权归作者所有,未经授权不得转载。Store,而必须通过 transact【关注微信公众号:wwwtangshuangnet】【访问 www.tangshuang.net 获取更多精彩内容】ion。

【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。【转载请注明来源】

transaction 方法有两个参数:

本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。

而通过 transaction 的 ob原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。jectStore 方法可以获取想要操作原创内容,盗版必究。【本文受版权保护】的 objectStore,但是它的参数【版权所有,侵权必究】【版权所有,侵权必究】必须存在于上面的 objectStore本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.nets 数组中,毕竟你的这个事务已经规定了要转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。对哪些 objectStore 进行操作【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】

【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】

因为 objectStore 是在事务中本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net获取,因此一个 objectStore 【未经授权禁止转载】【转载请注明来源】实例,如果有一个 transaction著作权归作者所有,禁止商业用途转载。【本文受版权保护】 属性的话,那么可以通过这个属性找出它的【原创内容,转载请注明出处】【本文首发于唐霜的博客】事务的实例。在 indexedDB 中,转载请注明出处:www.tangshuang.net原创内容,盗版必究。你只能在事务中得到一个 objectSt【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。ore 实例,如果通过 db 的话,最多【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】只能得到 objectStore 的名字转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net列表,要获得 objectStore 的【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net实例,必须在 transaction 中著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。

【关注微信公众号:wwwtangshuangnet】【转载请注明来源】【未经授权禁止转载】【原创内容,转载请注明出处】

补充:由于js是单线程运行程序,所以对于【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net所有事务而言,也是有先后顺序的,只有当某【未经授权禁止转载】【关注微信公众号:wwwtangshuangnet】些事务完成之后,才会进入后面当事务,因此【作者:唐霜】原创内容,盗版必究。即使一个 objectStore 存在于【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】多个事务中,它也会按照事务出现当先后顺序【作者:唐霜】【本文受版权保护】被操作,而不是被不同当事务交叉操作。另外【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。,对一个 objectStore 的写入【版权所有,侵权必究】未经授权,禁止复制转载。操作的事务只允许存在一个,它会自动根据你【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。传入的 mode 值为 readwrit原创内容,盗版必究。【本文首发于唐霜的博客】e 时进行判断和报错。

转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】
【本文受版权保护】【版权所有,侵权必究】【作者:唐霜】

事务生命周期

知道有事务的存在之后,一定要注意 indexedDB 事务的生【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】命周期。一个事务,它会把你在它的生命周期里面规未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。定的操作全部执行,一旦执行完,周期结束,【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】那么事务就关闭了,你不能再利用这个事务的【作者:唐霜】【访问 www.tangshuang.net 获取更多精彩内容】实例进行下一步操作。

【本文受版权保护】【本文受版权保护】【原创内容,转载请注明出处】

举一个错误的例子:

本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net
var tx
var objectStore
var request = indexedDB.open('name', 1)
requst.onsuccess = function(e) {
  var db = e.target.result
  tx = db.transaction(["MyOBJ"],"readwrite")
  objectStore = tx.objectStore("MyOBJ")
}
btn.onclick = function() {
  objectStore.add({}) // 这时会报错,因为生命周期已经结束了,你不能在这里使用 tx 或 objectStore
}

上面灰色的代码是一个错误的使用思路。写代本文版权归作者所有,未经授权不得转载。【本文受版权保护】码的人想在全局某个地方创建了一个事务,并【作者:唐霜】【版权所有】唐霜 www.tangshuang.net用一个变量保存起来,好在后续操作中使用。【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。但是,indexedDB 中,事务会在非未经授权,禁止复制转载。【本文受版权保护】常短的时间里面循环检查自己,当发现自己内【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】部已经没有任何任务要做的时候,就将自己关【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】闭。要深入了解这一点,你需要了解 jav【作者:唐霜】转载请注明出处:www.tangshuang.netascript 调用栈、事件循环的知识,未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net可能有点复杂。

著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】

总之,你可以把 indexedDB 里面转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】的事件想象成时间非常短(1ms)的 de【关注微信公众号:wwwtangshuangnet】【本文受版权保护】bounce,如果在这个 1ms 里面,著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。没有新的任务要做,它就关闭了,不能再被使著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】用。所以,上面正确的代码应该是:

【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net
btn.onclick = function() {
  var request = indexedDB.open('name', 1)
  requst.onsuccess = function(e) {
    var db = e.target.result
    var tx = db.transaction(["MyOBJ"],"readwrite")
    var objectStore = tx.objectStore("MyOBJ")
    var request = objectStore.add({ ... })
  }
}

即在每一次发生 click 事件的时候去【版权所有,侵权必究】【原创内容,转载请注明出处】发起一个事务,再在这个事务中搞事情。

【未经授权禁止转载】【本文受版权保护】

什么是 request?

我们操作数据,一定是在事务中进行。一个事【版权所有,侵权必究】【作者:唐霜】务,本质上是控制一个生命周期,用于保证数著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net据库读写的可用和安全。但是,真正涉及到如【作者:唐霜】【访问 www.tangshuang.net 获取更多精彩内容】何去存取数据,我们需要发起一个 requ【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】est。一个事务过程中,可以有多个 re【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.netquest,request 一定存在与事【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。务中,因此它肯定会有一个 transac本文作者:唐霜,转载请注明出处。【作者:唐霜】tion 属性来获取它所属于的那个事务的本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。容器。

著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】

为什么要有 request 呢?你可以把【本文首发于唐霜的博客】【原创内容,转载请注明出处】 transaction 当做一个队列,【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】在这个队列中,request 在进行排队本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。,每一个 request 都只包含一个操本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net作,比如添加,修改,删除之类的。这些操作【作者:唐霜】【访问 www.tangshuang.net 获取更多精彩内容】不能马上进行,比如修改操作,如果你马上进著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】行,就会导致大家同时修改怎么办的问题,把本文版权归作者所有,未经授权不得转载。【作者:唐霜】多个修改操作放在 request 中,这【未经授权禁止转载】转载请注明出处:www.tangshuang.net些 request 在 transact本文版权归作者所有,未经授权不得转载。【转载请注明来源】ion 中排队,一个一个处理,这样就会有【转载请注明来源】转载请注明出处:www.tangshuang.net执行的顺序,修改就有前后之分。同时,tr【转载请注明来源】原创内容,盗版必究。ansaction 都可以被 abort【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。,这样当一系列的操作被放弃之后,后续的操未经授权,禁止复制转载。【本文受版权保护】作也不会进行。

【本文受版权保护】著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】

而且非常重要的思想是,request 是【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net异步的,它有状态,一个 request 【版权所有,侵权必究】【原创内容,转载请注明出处】处于什么状态,可以通过 readyStates 属性查到,这对开发者而言也更可控。

【版权所有,侵权必究】【本文受版权保护】转载请注明出处:www.tangshuang.net

目前,在 indexedDB 中,有四种原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。可能产生 request:open da【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】tabase,objectStore r原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。equest, cursor reque转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.netst, index request。

【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net

cursor

虽然 indexedDB 使用 obje【版权所有】唐霜 www.tangshuang.net【作者:唐霜】ctStore 存储数据,是一个 key【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。-value 数据库。但是,我们有遍历所【作者:唐霜】本文版权归作者所有,未经授权不得转载。有记录的需求。cursor 游标,就是 【版权所有,侵权必究】【原创内容,转载请注明出处】indexedDB 提供的遍历整个 ob【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。jectStore 的能力接口。

本文版权归作者所有,未经授权不得转载。【作者:唐霜】【未经授权禁止转载】

什么是 cursor?

概念上讲,游标是“一个用来记录数组正在被【转载请注明来源】转载请注明出处:www.tangshuang.net操作的某个下标位置的迭代器”。举个例子,转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。你有一个数组 [1,2,3,4],现在你未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。要对它进行遍历,使用 forEach 方未经授权,禁止复制转载。【本文首发于唐霜的博客】法,那么 forEach 方法怎么知道你【原创不易,请尊重版权】未经授权,禁止复制转载。上次操作到第几个元素,现在应该操作第几个著作权归作者所有,禁止商业用途转载。【本文受版权保护】元素呢?它通过内部的一个迭代器实现。游标【版权所有,侵权必究】【未经授权禁止转载】本质上是一个迭代器,也就意味着有类似于 本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】next 的方法,可以用来移动游标到下一【本文首发于唐霜的博客】未经授权,禁止复制转载。个位置,有 value 属性用来读取当前原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】值。当然,游标不能理解为纯粹的迭代器,因【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。为它的内部过程需要进行 I/O 操作。

【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。

获取全部 object

想要获取一个 objectStore 中【未经授权禁止转载】本文作者:唐霜,转载请注明出处。的全部 object 可不是一件简单的事未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。。indexedDB 1.0 版本的时候原创内容,盗版必究。未经授权,禁止复制转载。没有直接提供类似的方法来获取(2.0 已【原创不易,请尊重版权】【本文受版权保护】经提供了 getAll 方法)。那么我们【转载请注明来源】【作者:唐霜】应该怎么办呢?利用游标。

原创内容,盗版必究。【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。
let transaction = db.transaction(['myObjectStore'], 'readonly')
let objectStore = transaction.objectStore('myObjectStore')
let request = objectStore.openCursor()
let results = []
request.onsuccess = e => {
  let cursor = e.target.result
  if (cursor) {
    results.push(cursor.value)
    cursor.continue()
  }
  else {
    // 所有的object都在results里面
  }
}

通过 openCursor 方法开启一个【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net游标,在其 onsuccess 事件中,【本文受版权保护】【未经授权禁止转载】如果 cursor 没有遍历完所记录,那本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net么通过执行 cursor.continu转载请注明出处:www.tangshuang.net【未经授权禁止转载】e() 来让游标滑动到下一个记录,ons原创内容,盗版必究。原创内容,盗版必究。ucess 会被再次触发。而如果所有记录【作者:唐霜】未经授权,禁止复制转载。都遍历完了,cursor 变量会是 un【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】defined。

转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】

注意上面蓝色的 results,它的声明【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】必须放在 onsuccess 回调函数的未经授权,禁止复制转载。【转载请注明来源】外部,因为该回调函数会在遍历过程中反复执【原创不易,请尊重版权】【原创内容,转载请注明出处】行。

原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net【本文受版权保护】著作权归作者所有,禁止商业用途转载。

通过 index 查询集合

前文举例过如何通过 index 查询值。著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。但是,在前面的演示代码中,仍然只能得到一原创内容,盗版必究。【原创不易,请尊重版权】个值,加入我们希望通过 index 得到【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。某个 index key 的所有值呢?通本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net过游标就可以实现。

转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。
let objectStore = db.transaction([storeName], 'readonly').objectStore(storeName)
let objectIndex = objectStore.index('name')
let request = objectIndex.openCursor()
request.onsuccess = e => {
  let cursor = e.target.result
  if (cursor) {
    results.push(cursor.value)
    cursor.continue()
  }
  else {
    // 所有的 object 都在 results 里面
  }
}

你可以发现,整个操作跟前面的获取所有 o著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.netbject 几乎一样,只不过这里先得到了【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。 index。

本文版权归作者所有,未经授权不得转载。【本文受版权保护】本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。

你也可以总结出游标的使用,简单的说,就是未经授权,禁止复制转载。【原创不易,请尊重版权】对已知的集合对象(比如 objectSt【原创不易,请尊重版权】【未经授权禁止转载】ore 或 index)进行遍历,在 o【原创不易,请尊重版权】【未经授权禁止转载】nsuccess 中使用 continu转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】e 来进行控制。

【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】【访问 www.tangshuang.net 获取更多精彩内容】

数据的存取

当一个事务开始之后,在它的生命周期以内,著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。你可以对 objectStore 进行数【本文受版权保护】本文版权归作者所有,未经授权不得转载。据操作,数据操作无非是增删改查。前面介绍转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。过如何获取事务中的objectStore【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】,现在,我们就用获取到的objectSt本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】ore进行数据操作。

【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。【未经授权禁止转载】

获取数据

let transaction = db.transaction(['myObjectStore'], 'readonly')
let objectStore = transaction.objectStore('myObjectStore')
let request = objectStore.get('100001')
request.onsuccess = e => {
  let obj = e.target.result
}

的确,在indexedDB事务机制下进行转载请注明出处:www.tangshuang.net【本文受版权保护】操作是很麻烦的,上面代码中我们使用了ge【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。t方法获取主键值为100001的obje转载请注明出处:www.tangshuang.net【作者:唐霜】ct,但是获取过程是一个Request,【转载请注明来源】【原创内容,转载请注明出处】后文会详细讲Request是什么东东,只著作权归作者所有,禁止商业用途转载。【作者:唐霜】有在其onsuccess事件中才能得到获本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】取到的结果。

原创内容,盗版必究。【未经授权禁止转载】原创内容,盗版必究。

添加数据

let transaction = db.transaction(['myObjectStore'], 'readonly')
let objectStore = transaction.objectStore('myObjectStore')
let request = objectStore.add({
  id: '100002',
  name: 'Zhang Fei',
})

添加数据使用add方法,传入一个obje【版权所有,侵权必究】【未经授权禁止转载】ct。但是这个object有限制,它的主【转载请注明来源】【版权所有,侵权必究】键值,也就是id值,不能是已存在的,如果本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。objectStore中已经有了这个id著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】,那么会报错。因此,在某些程序中,为了避本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】免这种情况的发生,我们使用put方法。

本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】

更新数据

let transaction = db.transaction(['myObjectStore'], 'readonly')
let objectStore = transaction.objectStore('myObjectStore')
let request = objectStore.put({
 id: '100002',
 name: 'Zhang Fei',
})

put方法和add方法有两大区别。一,如转载请注明出处:www.tangshuang.net【未经授权禁止转载】果objectStore中已经有了该id【未经授权禁止转载】【关注微信公众号:wwwtangshuangnet】,则表示更新这个object,如果没有,【未经授权禁止转载】【版权所有,侵权必究】则添加这个object。二,在另一种情况【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。下,也就是设置了autoIncremen【本文受版权保护】本文作者:唐霜,转载请注明出处。t为true的时候,也就是主键自增的时候【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】,put方法必须传第二个参数,第二个参数【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。是主键的值,以此来确定你要更新的是哪一个【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。主键对应的object,如果不传的话,可【转载请注明来源】转载请注明出处:www.tangshuang.net能会直接增加一个object到数据库中。【原创不易,请尊重版权】【未经授权禁止转载】从这一点上讲,自增字段确实比较难把握,因【本文首发于唐霜的博客】【原创内容,转载请注明出处】此我建议开发者严格自己在传入时保证obj【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】ect中存在主键值。

【未经授权禁止转载】【本文受版权保护】【原创不易,请尊重版权】【作者:唐霜】

删除数据

let transaction = db.transaction(['myObjectStore'], 'readonly')
let objectStore = transaction.objectStore('myObjectStore')
let request = objectStore.delete('100001')

delete方法把你传入的主键值对应的o【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.netbject从数据库中删除。

【关注微信公众号:wwwtangshuangnet】【转载请注明来源】【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net

IndexedDB API

本节主要把indexedDB中最常用的所【原创不易,请尊重版权】原创内容,盗版必究。有api进行列举,起到快速查阅的作用。注原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net意,这里仅是最常用,基本可以覆盖90%的【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net使用场景,但并不代表所有的api都在这里原创内容,盗版必究。【本文受版权保护】,你可以通过这里查阅全部。

【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net【本文受版权保护】【关注微信公众号:wwwtangshuangnet】

IDBDatabase

也就是本文最开始使用open打开inde【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。xedBD得到的db对象db,通过这节,了解这个idb有些什么接口可本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net以被调用。

著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。
let request = indexedDB.open(name, version)
request.onsuccess = (e) => {
  let db = e.target.result // 获得db
}

name

通过idb.name获取当前连接到的数据【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。库的名字。这和你在open的时候传入的n本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。ame是一致的。

原创内容,盗版必究。【转载请注明来源】

version

和你在open的时候传入的version转载请注明出处:www.tangshuang.net【版权所有,侵权必究】是一致的。

本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】

objectStoreNames

获取当前数据库的所有objectStor【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.nete的name列表,是一个数组。

【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】本文作者:唐霜,转载请注明出处。

createObjectStore()

创建一个objectStore,有两个参本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。数:

本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net

例子:

原创内容,盗版必究。【原创不易,请尊重版权】原创内容,盗版必究。【原创不易,请尊重版权】
db.createObjectStore('students', { keyPaht: 'id', autoIncrement: false })

deleteObjectStore()

删除一个objectStore,参数只有【访问 www.tangshuang.net 获取更多精彩内容】【转载请注明来源】一个:

原创内容,盗版必究。原创内容,盗版必究。

删除的时候,它的所有index也被删除了【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】

【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。

close()

关闭当前打开的这个数据库。关闭之后,任何本文作者:唐霜,转载请注明出处。【本文受版权保护】操作都会报错。

【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】

transaction()

重头戏,开启一个事务,是后续操作的开始。【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.net前文已经讲过了,任何操作都是要在事务中进【作者:唐霜】本文作者:唐霜,转载请注明出处。行的,对于一个database而言,如果【版权所有,侵权必究】【版权所有,侵权必究】要获取里面的数据,或者修改其中的某一个o本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】bjectStore,都要通过这个方法来【转载请注明来源】原创内容,盗版必究。开启一个事务,在事务中进行操作。

本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。

它有两个参数:

未经授权,禁止复制转载。【原创内容,转载请注明出处】未经授权,禁止复制转载。【未经授权禁止转载】

我们用代码来看下用法:

【作者:唐霜】著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。
let tx = idb.transaction(['students'], 'readonly')

这样就获得了一个database的事务容著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。器。

【关注微信公众号:wwwtangshuangnet】【作者:唐霜】【作者:唐霜】

database的api主要用到的就这些转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。了,接下来,我们来看下,开启事务之后,我原创内容,盗版必究。未经授权,禁止复制转载。们可以干什么。

【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net

IDBTransaction

关于transaction的概念前面已经【本文首发于唐霜的博客】【作者:唐霜】说了,这里主要看下,得到一个transa本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。ction之后可以干什么。

【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。

db

获取这个transaction是对哪个d【本文受版权保护】【未经授权禁止转载】atabase进行操作的事务。

【转载请注明来源】【原创内容,转载请注明出处】未经授权,禁止复制转载。【原创内容,转载请注明出处】

objectStoreNames

这个事务要对哪些objectStore进【原创内容,转载请注明出处】原创内容,盗版必究。行操作,和你传入的objectStore【本文首发于唐霜的博客】【原创内容,转载请注明出处】Names是一致的,是一个数组。

【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】

mode

读写权限,和你传入的mode一致。

【作者:唐霜】著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net

abort()

终止该事务,一旦人为终止,你程序中的某些【本文受版权保护】【版权所有】唐霜 www.tangshuang.net操作就不会再执行了。

【版权所有】唐霜 www.tangshuang.net【作者:唐霜】

objectStore()

获取事务中的某个objectStore的【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。容器。它有一个参数:

【版权所有】唐霜 www.tangshuang.net【转载请注明来源】原创内容,盗版必究。

获得该objectStore容器之后,就转载请注明出处:www.tangshuang.net原创内容,盗版必究。可以利用它进行objectStore的数本文版权归作者所有,未经授权不得转载。【本文受版权保护】据增删改查了。

【本文受版权保护】本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。【版权所有,侵权必究】
let tx = idb.transaction(['students'], 'readonly')
let objStore = tx.objectStore('students')

// 利用objStore进行查询:
let request = objStore.get('100001')

注意,它的参数必须是在transacti【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】on的第一个参数数组中的。

【本文受版权保护】著作权归作者所有,禁止商业用途转载。【作者:唐霜】

IDBObjectStore

重头戏,objectStore是最核心的著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net概念了,它的容器,也就是上面这段代码中的objStore,都可以进行哪些后续操作呢?

未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net

name

获取该objectStore的name。著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。和创建的时候传入的name一致。

【版权所有,侵权必究】【未经授权禁止转载】转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】

keyPath

和创建的时候传入的keyPath一致。

【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。

autoIncrement

和创建的时候传入的autoIncreme著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。nt一致。

【本文受版权保护】转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。

indexNames

获取该objectStore的所有索引的本文版权归作者所有,未经授权不得转载。【本文受版权保护】命名列表,和createIndex传入的著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】第一个参数一致。

著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】

transaction

获取该objectStore所属的tra【本文受版权保护】著作权归作者所有,禁止商业用途转载。nsaction的容器。一个object未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。Store的容器,只有在事务中才能得到,【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】因此这个objectStore的容器一定著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net属于某个事务,那么也就有对应的trans【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。action容器。通过transacti原创内容,盗版必究。【本文首发于唐霜的博客】on容器,其实可以做很多操作,比如获取和本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net该objectStore一起操作的其他o原创内容,盗版必究。本文作者:唐霜,转载请注明出处。bjectStore的name。

原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】

get()

发起一个获取object的Request【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net。Request我们还没有讲到,后面会讲本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】。它有一个参数:

本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】【作者:唐霜】【关注微信公众号:wwwtangshuangnet】

代码说话:

【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】
let objStore = tx.objectStore('students')
let request = objStore.get(100001)

而要得到最后查询到的object,需要在未经授权,禁止复制转载。原创内容,盗版必究。request的onsuccess中获取【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。。所以后面讲完Request之后,你就能原创内容,盗版必究。原创内容,盗版必究。正确使用代码了。

著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。

add()

发起一个添加object的Request转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。。它有一个参数:

本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。

还是用代码来看下:

【本文受版权保护】【版权所有,侵权必究】
let objStore = tx.objectStore('students')
let request = objStore.add({
  id: '100002',
  name: 'Li Hua',
})

delete()

发起一个删除object的Request【转载请注明来源】未经授权,禁止复制转载。。它有一个参数:

【本文受版权保护】本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。【未经授权禁止转载】

put()

发起一个更新某个object的Reque本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。st。它有两个参数:

原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。

关于key非常难理解。当你在创建一个ob【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。jectStore的时候,你可能会传入a【原创不易,请尊重版权】原创内容,盗版必究。utoIncrement为true,这时【本文受版权保护】【版权所有】唐霜 www.tangshuang.net,这个objectStore和我们经常使本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。用的有点不同。比如你的主键是id,那么如【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】果你在add或put的时候,不传这个id【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net,id值会自动加1,你get到的obje转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】ct也会包含id属性。

著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】

当你在使用put方法去更新的时候,如果你【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。的objectStore的autoInc本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。rement是true,就必须传入第二个【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net参数key,put方法会先通过key找到转载请注明出处:www.tangshuang.net【版权所有,侵权必究】该object,然后在用object的内【转载请注明来源】【转载请注明来源】容去更新。而如果不传key,那么你传入的【本文首发于唐霜的博客】原创内容,盗版必究。第一个参数object中必须包含id,否著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net则会报错。
【访问 www.tangshuang.net 获取更多精彩内容】 但是如果你的autoIncrement【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。设置的是false,那就可以考虑忽略ke【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.nety。但是效果还是不一样,当你传入key值转载请注明出处:www.tangshuang.net原创内容,盗版必究。的时候,会更新传入的key对应的那个ob【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】ject。不传的时候,根据你object【未经授权禁止转载】未经授权,禁止复制转载。里面的主键来更新,没有的话会被认为是ad著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.netd操作,不会报错。

【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】

所以比较好的一种操作是,不设置autoI未经授权,禁止复制转载。原创内容,盗版必究。ncrement,无论是添加还是修改ob著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。ject,都使用put,只要开发者自己注转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。意,传入的object一定要有一个主键即【本文首发于唐霜的博客】【作者:唐霜】可。这样当存在该主键值时,就更新,不存在【本文受版权保护】【版权所有,侵权必究】时就插入。这比使用add好很多,因为ad本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。d的时候,如果存在会报错。

【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。

如果你还有不理解的地方,欢迎在下方留言,【作者:唐霜】转载请注明出处:www.tangshuang.net对这个问题进行探讨。

本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。

count()

没有参数,发起一个查询当前objectS未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。tore的所有object的数量的Req本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。uest。

【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】未经授权,禁止复制转载。

clear()

没有参数,发起一个删除objectSto【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。re里面的所有object的Reques本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。t。

著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net

清除数据之前请备份好数据。

【转载请注明来源】【转载请注明来源】原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。

openCursor()

发起一个打开游标的Request。它的参【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】数统一在IDBCursor中讲。

未经授权,禁止复制转载。【版权所有,侵权必究】【转载请注明来源】

index()

通过index方法,可以建立一个类似SQ【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。L数据库中视图。它先得到一个IDBInd【作者:唐霜】原创内容,盗版必究。ex,然后你在对这个IDBIndex进行本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。操作。因此它不是发起一个Request,【作者:唐霜】【关注微信公众号:wwwtangshuangnet】这有别于前面的方法。返回的IDBInde【原创不易,请尊重版权】【原创不易,请尊重版权】x会在下文详细描述它的API。index著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】方法由一个参数:

本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】

看下代码怎么用:

【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】【本文首发于唐霜的博客】
let objStore = tx.objectStore('students')
let objIndex = objStore.index('name')
let request = objIndex.get('Li Hua')

createIndex()

创建一个索引,和前面的方法不同,它不是发【转载请注明来源】原创内容,盗版必究。起一个Request,而是直接进行操作,【版权所有,侵权必究】【转载请注明来源】并且返回一个IDBIndex。关于IDB【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。Index,我会在Request后面再讲【原创不易,请尊重版权】【作者:唐霜】。它有三个参数:

转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】

虽然objectParameters还有【作者:唐霜】转载请注明出处:www.tangshuang.net其他选项,但是常用的就是unique。

本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net

注意,只能在onupgradeneede【原创内容,转载请注明出处】【本文首发于唐霜的博客】d中使用。

未经授权,禁止复制转载。【作者:唐霜】原创内容,盗版必究。

deleteIndex()

删除一个索引,也不用发起Request。【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】它有一个参数:

【版权所有,侵权必究】【未经授权禁止转载】【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】

删除索引之后,就不能再根据索引查询数据了【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】

本文作者:唐霜,转载请注明出处。【本文受版权保护】

另外需要注意,创建和删除索引,都需要在打【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。开db的Request的onupgrad【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。eneeded事件中完成。

【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net

IDBRequest

前面一直强调事务的概念,没有对Reque原创内容,盗版必究。未经授权,禁止复制转载。st进行介绍。Request是在事务过程原创内容,盗版必究。【作者:唐霜】中,发起某项操作的请求。一个事务过程中,【原创内容,转载请注明出处】【原创不易,请尊重版权】可以有多个Request,Request【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】一定存在与事务中,因此它肯定会有一个tr【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.netansaction属性来获取它所属于的那原创内容,盗版必究。转载请注明出处:www.tangshuang.net个事务的容器。

原创内容,盗版必究。【本文首发于唐霜的博客】

目前,在indexedDB中,有四种可能【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net产生Request:open datab原创内容,盗版必究。未经授权,禁止复制转载。ase,objectStore requ【版权所有,侵权必究】未经授权,禁止复制转载。est, cursor request,【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。 index request。

未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。

readyState

Request的状态。只有两种状态:pe【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】nding, done。

【作者:唐霜】【本文首发于唐霜的博客】【未经授权禁止转载】

transaction

获取该Request所属于的transa著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。ction。

【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。

source

获取该Request是由谁发起的,它可能【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net有四种情况:objStore, curs【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】or, index, null. 当该R【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】equest是open database本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。的时候发起,source值为null。

【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】【转载请注明来源】

通过该source值,其实可以获取更多信【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】息,比如objectStore的其他信息【版权所有,侵权必究】【本文首发于唐霜的博客】

【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。

result

获取该Request的输出结果。该值最开著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】始是undefined,只有当Reque【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.netst成功之后,该值才会出现。因此,要获取著作权归作者所有,禁止商业用途转载。【作者:唐霜】一个get的最终结果,必须在Reques【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。t的onsuccess事件中调用:

【作者:唐霜】未经授权,禁止复制转载。
let request = objectStore.get(10001)
request.onsuccess = e => {
  let item = request.result
  // 等价于
  let item = e.tareget.result
}

IDBIndex

索引的概念就不讲了,这里主要是把最常用的本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】有关所有的api列举出来,方便使用。

转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】【原创不易,请尊重版权】

什么情况下会产生IDBIndex呢?当调著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】用一个objectStore的index【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net方法时,前文在讲IDBObjectSto【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.netre的时候已经讲到过了。

未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。
let objStore = tx.objectStore('students')
let objIndex = objStore.index('name')

通过index方法之后,这个objInd【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.netex可以进行哪些操作呢?

【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】

name

该属性可以获取index的name。

【版权所有,侵权必究】转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】

keyPath

该属性可以获取index的keyPath【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。,也就是object的某个属性的名字。这【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】个你在createIndex的时候传入的本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。keyPath是一致的。

【版权所有,侵权必究】未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net

unique

返回是否是唯一的,和你createInd转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。ex的时候传入的值是一致的。

【原创不易,请尊重版权】【未经授权禁止转载】【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net

isAutoLocale

返回一个boolean值,它表示这个in【未经授权禁止转载】【本文受版权保护】dex是否是自增的,和前面的autoIn【版权所有,侵权必究】转载请注明出处:www.tangshuang.netcrement有关。

【本文受版权保护】著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net

locale

如果这个index对应的字段是自增的,那【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。么现在的自增基础值是多少?比如你的id是【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】自增的,现在objectStore里面有转载请注明出处:www.tangshuang.net【未经授权禁止转载】10个object,这时objIndex【本文受版权保护】本文作者:唐霜,转载请注明出处。.locale应该是10.

未经授权,禁止复制转载。【未经授权禁止转载】

objectStore

因为IDBIndex总是通过object【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.netStore的index方法产生的,所以它【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net自然会有对应的那个objectStore本文版权归作者所有,未经授权不得转载。【本文受版权保护】,而自己的objectStore属性正好【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】是一个引用,指向那个产生自己的objec【作者:唐霜】【原创内容,转载请注明出处】tStore。

【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】

count()

发起一个当前index视图总共有多少个o本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.netbject的Request。

著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net【转载请注明来源】【本文首发于唐霜的博客】

get()

发起一个从当前index获取一个值为传入【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】参数的object的Request。它有著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】一个参数:

著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】

这里的key有点难理解,前面object【作者:唐霜】【未经授权禁止转载】Store的get方法传入的是主键的值,【版权所有,侵权必究】原创内容,盗版必究。而这类的get传入的是你选择的这个索引对著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】应的属性的值。比如说:

【版权所有,侵权必究】【本文首发于唐霜的博客】
{
  id: 1,
  name: 'tom',
}

id是主键,name是一个索引。那么这个【原创内容,转载请注明出处】【原创内容,转载请注明出处】时候,如果你想得到这个object,应该转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。使用:

【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。
let request = objIndex.get('tom') // 这个tom是name属性的值

openCursor()

发起一个打开游标的Request。它的参【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net数统一在IDBCursor中讲。

【转载请注明来源】原创内容,盗版必究。原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】

可以看出,objIndex对于objSt【未经授权禁止转载】【作者:唐霜】ore而言,方法少了很多,它不能更新、删【原创内容,转载请注明出处】【作者:唐霜】除等。但是实际上,通过objectSto【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。re属性,就可以反过来对objectSt著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】ore进行操作。

原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】【转载请注明来源】

IDBCursor

游标通过前文的阐述,应该比较容易理解了。未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net这里我们来看下,一个cursor都可以进【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】行哪些操作。

本文作者:唐霜,转载请注明出处。【本文受版权保护】本文版权归作者所有,未经授权不得转载。【作者:唐霜】

但是在开始之前,你要回头看下游标是怎么得本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net到的?

【作者:唐霜】原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】

openCursor()

objectStore或objectIn原创内容,盗版必究。原创内容,盗版必究。dex可以使用这个方法打开一个游标的Re【本文首发于唐霜的博客】原创内容,盗版必究。quest。它有两个参数:

本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】

打开游标后,游标怎么获得呢?在Reque【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】st的onsuccess中得到的:

著作权归作者所有,禁止商业用途转载。【本文受版权保护】【版权所有】唐霜 www.tangshuang.net
objStore.openCursor().onsuccess = e => {
  let cursor = e.target.result // 这个才是我们要的游标
}

接下来就是看看,这个cursor有哪些接【本文受版权保护】【转载请注明来源】口。

本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】

direction

游标遍历的方向,方向前面说过了,和你op【未经授权禁止转载】转载请注明出处:www.tangshuang.netenCursor的时候传入的是一致的。

【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】【本文受版权保护】

key

把当前游标所在的那个object的值返回【本文受版权保护】【原创内容,转载请注明出处】给你,这个值是你使用index方法时,选未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net择的那个索引对应的属性的值。有点绕,举个未经授权,禁止复制转载。原创内容,盗版必究。例子,如果游标当前停留在:

【版权所有,侵权必究】未经授权,禁止复制转载。【原创不易,请尊重版权】
{
  id: 2,
  name: 'sue',
}

而你开启这个游标,又是通过objStore.index('name').openCursor()开启的,那么这个时候这个key值,就是s本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】ue了。

转载请注明出处:www.tangshuang.net【转载请注明来源】【原创内容,转载请注明出处】【作者:唐霜】

primaryKey

游标遍历所在位置的object的主键。这【版权所有】唐霜 www.tangshuang.net【本文受版权保护】个比较难理解,key和primaryKe【原创内容,转载请注明出处】原创内容,盗版必究。y的区别主要体现在你用索引进行检索的时候本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。,如果你openCursor是在非索引集著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。合情况下,其实key和primaryKe【转载请注明来源】著作权归作者所有,禁止商业用途转载。y是一样的,因为都是以主键作为索引。但是【本文首发于唐霜的博客】【本文受版权保护】当你用index方法筛选出子集,那么这个著作权归作者所有,禁止商业用途转载。【本文受版权保护】时候primaryKey在某些情况下就非未经授权,禁止复制转载。【原创不易,请尊重版权】常有必要知道。

【本文受版权保护】转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。

source

该属性返回开启游标的容器的引用,也就是o本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.netbjStore或objIndex。

本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。

value

改属性返回当前遍历到的object,严格【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。的说,这个属性是IDBCursorWithValue的属性。

【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。

continue()

游标往下移动一格或移动到你规定的位置。注本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。意,它是根据你规定的方向进行移动的。它可【原创内容,转载请注明出处】【本文首发于唐霜的博客】以有一个参数:

转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】

advance()

continue()是只移动一格,adv【未经授权禁止转载】【版权所有,侵权必究】ance()可以自己规定移动的格数。它有【未经授权禁止转载】【原创内容,转载请注明出处】一个参数:

未经授权,禁止复制转载。【原创内容,转载请注明出处】【本文受版权保护】【版权所有,侵权必究】

continuePrimaryKey()

前面讲了primaryKey这个属性,也【原创不易,请尊重版权】【原创不易,请尊重版权】讲了continue(key)这个方法的【本文受版权保护】【本文受版权保护】参数key。但是,当你在openCurs未经授权,禁止复制转载。【版权所有,侵权必究】or的时候,索引的值可重复时,那就会出现【本文受版权保护】【版权所有,侵权必究】尴尬的情况。在objectStore里面【作者:唐霜】原创内容,盗版必究。存储数据的时候,primaryKey和其著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】他索引的key,它们的值可能是重复的,但原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。是如果通过两个key的值来确定呢?那么就【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。能更准确的定位某一个object。因此,【本文受版权保护】本文作者:唐霜,转载请注明出处。当你使用continuPrimaryKe【转载请注明来源】本文作者:唐霜,转载请注明出处。y的时候,是为了解决这个问题,即cont【未经授权禁止转载】【版权所有,侵权必究】inue()只会根据参数,往下移动到下一【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】个给定参数值的object,而如果使用c【作者:唐霜】未经授权,禁止复制转载。ontinuePrimaryKey(),【本文首发于唐霜的博客】【本文首发于唐霜的博客】那么在往下一个给定值移动时,还会再考虑p【转载请注明来源】【未经授权禁止转载】rimaryKey的值。

【本文首发于唐霜的博客】【原创不易,请尊重版权】原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。

一般来说primaryKey的值都是唯一未经授权,禁止复制转载。【原创内容,转载请注明出处】的,但也不排除有些情况不唯一的时候,这个【未经授权禁止转载】【原创不易,请尊重版权】时候,使用游标结合continuePri原创内容,盗版必究。【本文受版权保护】maryKey才能正确获得你想要的那个o原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。bject,通过普通的get只能得到第一【未经授权禁止转载】转载请注明出处:www.tangshuang.net个object。

原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net

delete()

发起一个删除当前游标所在的object的本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】Request。删除之后,就要考虑用co未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。ntinuePrimaryKey(),而【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。不是continue()。

未经授权,禁止复制转载。【本文受版权保护】

update()

发起一个更新当前游标所在的这个objec本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。t的对应字段的值的Request。它有一【关注微信公众号:wwwtangshuangnet】本文作者:唐霜,转载请注明出处。个参数:

著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。

小结

本文所有的内容就讲完了,本文从 Inde【本文受版权保护】原创内容,盗版必究。xedDB 的概念和结构开始,把所有常用【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】的 API 都讲了一遍,并且还给出了很多未经授权,禁止复制转载。未经授权,禁止复制转载。例子。
【作者:唐霜】 有人做过一个预测,Web SQL 数据原创内容,盗版必究。本文作者:唐霜,转载请注明出处。库已经从标准中移除了,有可能在后面的浏览转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net器版本中被去除,IndexedDB 将有【版权所有,侵权必究】转载请注明出处:www.tangshuang.net可能统一浏览器本地化存储的数据库。

【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。

虽然本文对大部分 IndexedDB 的【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net接口都进行了讲解,但是还只是入门教程,还转载请注明出处:www.tangshuang.net原创内容,盗版必究。有很多东西没讲。举个例子,作为数据库,最【原创内容,转载请注明出处】【本文受版权保护】重要的就是检索功能,也就是索引检索的那个【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】部分,但是本文并没有对这个部分展开。索引【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】检索还可以实现阈值检索,比如检索某一段日【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。期内的所有 object,比如检索所有同转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。姓氏的同学,这些问题都是经常遇到的,但都【转载请注明来源】著作权归作者所有,禁止商业用途转载。不再本文的讲解范围内。想要完全了解 in【版权所有】唐霜 www.tangshuang.net【作者:唐霜】dexedDB,还需要你继续深入学习。

【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】

参考文献

  1. HTML5 indexedDB前端本地存【本文首发于唐霜的博客】【未经授权禁止转载】储数据库实例教程
  2. 【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】
  3. indb 可能是最便捷的 indexedDB 操【本文首发于唐霜的博客】【原创内容,转载请注明出处】作库
  4. 转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】
  5. Dexie.js 将 indexeddb 封装成类 sq【原创不易,请尊重版权】未经授权,禁止复制转载。l 操作的库
  6. 【原创内容,转载请注明出处】【原创不易,请尊重版权】【作者:唐霜】未经授权,禁止复制转载。

如果你觉得本书对你有帮助,通过下方的二维码向我打赏吧,帮助我写出更多有用的内容。

2017-09-09 |

已有11条评论
  1. Feng 2024-09-23 11:13

    文章中的部分图片失效了

    • 否子戈 2024-10-05 22:50

      CDN域名证书过期了,已经修复

  2. Liang 2023-04-01 08:14

    最近在做ChatGPT相关的一个项目,想在浏览器本地保存聊天记录,才知道了有内置 indexedDB 这个数据库,在尝试之后发现好难用!

    在网上搜索到了 Dexie.js 封装了相关的 API,找中文教程时顺藤摸瓜找到了博主的文章,非常感谢您,写得很详细,很多我不理解东西都被讲明白了,今晚尝试一下!

  3. 傅莺仟 2022-12-29 13:51

    我想请教一个问题,indexdb上存储的数据怎么可以转移到另外一个pc端(假设数据量比较大,除了通过将数据全部查询出来,然后再一条一条导入新的的pc端,还有什么好的办法吗?)

    • 否子戈 2023-01-03 11:16

      indexeddb属于本地持久化存储,它设计的目标就是本地存储,不是共享,如果你是要共享数据,应该是搭数据服务,如果只是为了做数据迁移,目前没有更好的办法,自己写个程序把库导出为一个json,再发送给另外一个用户写个导入程序

  4. Coolkk 2020-02-22 00:27

    感谢教程。

  5. 老李 2019-12-02 10:05

    感謝大大分享
    非常實用且完整
    解釋淺顯易懂
    讓在網路上自學的我收穫匪淺

  6. ospider 2018-02-28 01:40

    关于版本那一块,好像文中也没有详细解释了,如果有时间,还请写一下呀

    > 这时你会想,如果我从新的version切换为老的version,还可以在老的version里面添加数据吗?这个问题我们暂时保留。

    • 否子戈 2018-02-28 14:11

      在文章中添加来补充内容,关于降级我没有实际测试过,如果你有兴趣对话,可以试一下。

  7. ospider 2018-02-26 18:59

    代码都被压成一行了。。大佬有时间改下么

    • 否子戈 2018-02-28 13:09

      谢谢提醒