IndexedDB 中文教程

IndexedDB 中文教程

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

前言

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

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

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

【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。
【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。

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

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

架构体系

这里说的结构体系,是指在 indexed【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。DB 中,几个重要的概念之间的关系。这些【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】概念包括:

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

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

著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】【原创内容,转载请注明出处】

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

关系型数据库和非关系型数据库本身有非常大本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】的差别,关系型数据库大致上架构是一致的,本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。但是非关系型数据库的架构各式各样,很不统【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。一。就 SQL DB 和 indexed【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。DB 而言:

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

indexedDB 中的 objectS【关注微信公众号:wwwtangshuangnet】【访问 www.tangshuang.net 获取更多精彩内容】tore 虽然和 SQL DB 中的 t本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】able 非常像,但是它们的存储形式却极【版权所有,侵权必究】【原创内容,转载请注明出处】其不同。objectStore 比 ta原创内容,盗版必究。转载请注明出处:www.tangshuang.netble 简单的多。

【转载请注明来源】【本文受版权保护】著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】

同时,indexedDB 内置了事务系统【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net,所有读写操作都是在事务中完成。

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

数据库

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

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

连接数据库

要在 indexedDB 中存储数据,要【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net进行两步操作,第一步连接到某个数据库,第【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】二步挑选某个 objectStore 进【本文受版权保护】著作权归作者所有,禁止商业用途转载。行数据操作。现在讲解连接到 indexe【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。dDB 数据库。在 window 对象上未经授权,禁止复制转载。【未经授权禁止转载】有一个 indexedDB 对象,直接调原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。用 open 方法进行打开,如果该数据库著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】不存在,则创建一个新的数据打开:

【版权所有】唐霜 www.tangshuang.net【转载请注明来源】【版权所有,侵权必究】
const request = window.indexedDB.open('mydb', 1)

open有两个参数:

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

数据库版本

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

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

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

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

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

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

在MDN里面有这样一句话:When you call open()原创内容,盗版必究。【原创内容,转载请注明出处】 with a greater vers【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】ion than the actual 【版权所有】唐霜 www.tangshuang.net【转载请注明来源】version of the datab未经授权,禁止复制转载。原创内容,盗版必究。ase, all other open 本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。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【转载请注明来源】原创内容,盗版必究。t is fired until the【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】y are closed or relo【原创内容,转载请注明出处】【本文受版权保护】aded). 也就是说,1. 你要传入一个更大当版本【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。来触发 onupgradeneeded,著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。2. 在数据库处于 open 状态时,对【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】数据库对修改是被 block 住,直到它【本文首发于唐霜的博客】【作者:唐霜】被 close 或 reload 之后,本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net这些修改才会生效。

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

现在你需要记住的是,在后面的代码操作中,【作者:唐霜】【版权所有】唐霜 www.tangshuang.net你要时刻保证你使用对了 version,【本文首发于唐霜的博客】【作者:唐霜】它的使用场景只有两种:

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

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

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

获得 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【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。ccess 的函数体内继续写代码。而且 本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】indexedDB 的所有编程都是这样,【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。这会导致嵌套层层加深,因此,我们这篇文章【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net后面还会提供使用 Promise 进行封未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。装的类,使用该类你无需做复杂的操作。

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

objectStore

objectStore 是 indexe【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】dDB 中非常核心的概念,它是数据的存储【作者:唐霜】本文版权归作者所有,未经授权不得转载。仓库,一个 objectStore 类似【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。于 SQL 数据库中的表,存放着相关的所【原创不易,请尊重版权】【原创内容,转载请注明出处】有数据记录。

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

什么是 objectStore?

indexedDB 是 key-valu【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.nete 数据库,具体体现就是 objectS原创内容,盗版必究。【版权所有,侵权必究】tore. objectStore 是 【转载请注明来源】【未经授权禁止转载】indexedDB 的数据存储机制,和 【作者:唐霜】【本文受版权保护】SQL 的表的地位一致。每一条记录包含了【本文受版权保护】【本文受版权保护】 key 和 value。

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

未经授权,禁止复制转载。【转载请注明来源】

indexedDB 之所以将自己的存储机【关注微信公众号:wwwtangshuangnet】【作者:唐霜】制称为 objectStore,在 st【转载请注明来源】【关注微信公众号:wwwtangshuangnet】ore 前面加上 object,是因为它【原创不易,请尊重版权】【版权所有,侵权必究】所存储的记录的集合,就像一个 objec转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】t 一样,是一个 key-value 的本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net集合。

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

什么是 key?

key 是 value 的标记值。

原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】

我们通过 key 得到 indexedD著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。B 中存储的对应值。要获得 value,本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】必须通过 key 来获得。key 和 v著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】alue 具有绑定关系,key 相当于 【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.netvalue 的缩写、别名、标记。

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

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

【原创不易,请尊重版权】未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】

原创内容,盗版必究。【本文受版权保护】

上图中上面一条记录的 value 是一个【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net对象,key 来自对象的 id 属性值,未经授权,禁止复制转载。【原创不易,请尊重版权】这个 key 是 inline key。【关注微信公众号:wwwtangshuangnet】【作者:唐霜】下面一条记录,value 是一个字符串,【关注微信公众号:wwwtangshuangnet】【转载请注明来源】key 是由系统自动生成,这个 key 【本文首发于唐霜的博客】原创内容,盗版必究。是 outline key。

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

例如有一个值是 { body: { color: 'red' } } 而 keyPath 为 body.color,那么就可以得到 key 为 red。这可能和我们以前理解的地方有所不同。在【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。 IndexedDB 中,我们要通过 r著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】ed 去找到这个值。

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

什么是 keyPath?

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

【本文受版权保护】【本文首发于唐霜的博客】未经授权,禁止复制转载。
{
  books: [
    { name: 'My Uncle Tom', price: 13.4 }
  ],
}

其中我要获得第一本书的价格,那么它的 k【版权所有】唐霜 www.tangshuang.net【本文受版权保护】eyPath 就是 ‘boo【本文首发于唐霜的博客】【原创不易,请尊重版权】ks[0].price’。它著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。是一个字符串,但可以用来表达获得一个节点【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】值的属性路径。所以,keyPath 这个【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。单词中的 path 就是这个意思。

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

key 和 keyPath 的联系

keyPath 的作用是读取 key。

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

key 是 value 的 keyPat著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。h 的值。

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

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

【未经授权禁止转载】【作者:唐霜】

一般而言,keyPath 在创建 obj【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.netectStore 和 index 的时候著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。就已经确定了,不会改。所以,在实际编程的原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】时候,我们很少会去用 keyPath,而转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net是拿到一个 key 进行操作。

转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】

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

【关注微信公众号:wwwtangshuangnet】【作者:唐霜】未经授权,禁止复制转载。

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

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

可以存储哪些数据类型?

根据 w3c 文档描述,indexedDB 可以存储的数据类型【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】为:

转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net

String, Date, Object本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】, Arra, FileBlobImageData等等。另外,网上很多人指出,支持存储 A【关注微信公众号:wwwtangshuangnet】【本文受版权保护】rrayBuffer。

【未经授权禁止转载】转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】

根据 w3c 的描述,凡是能进行序列化的【转载请注明来源】本文版权归作者所有,未经授权不得转载。值,都可以被 indexedDB 存储。【本文受版权保护】【原创不易,请尊重版权】也就是说,不能被序列化的,例如自引用的 【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】object,或者某些类的实例,还有 f【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。unction,就不能被 indexed本文作者:唐霜,转载请注明出处。原创内容,盗版必究。DB 存储。简单理解就是,不能存func【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】tion等非结构化的数据,object必【版权所有,侵权必究】【原创内容,转载请注明出处】须是以键值对组成的字面对象。

【未经授权禁止转载】原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net【作者:唐霜】

创建 objectStore

创建 objectStore 和修改 o【本文受版权保护】本文作者:唐霜,转载请注明出处。bjectStore 都只能在 db 的 onupgradeneeded 事件中进原创内容,盗版必究。【原创不易,请尊重版权】行,因此,要创建 objectStore【作者:唐霜】未经授权,禁止复制转载。,必须在前面的 open 操作那个时候来本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net进行。

本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。【作者:唐霜】
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【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。jectStore 的创建。但是,需要注原创内容,盗版必究。本文作者:唐霜,转载请注明出处。意的是,一个 database 中,只允【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。许存在一个同名的 objectStore原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。,因此,如果你第二次 createObj本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。ectStore 相同名的objectS原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.nettore,程序会报错。比如你的程序如果像本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。上面这样写,必然会遇到一个问题,就是当你本文作者:唐霜,转载请注明出处。【作者:唐霜】更新 version 的时候,会再次执行转载请注明出处:www.tangshuang.net原创内容,盗版必究。 createObjectStore,那本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。么就会报错,程序就会中断。另一个注意点是著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】,一旦一个 objectStore 被创【作者:唐霜】著作权归作者所有,禁止商业用途转载。建,它的 name 和 keyPath 【版权所有,侵权必究】【原创内容,转载请注明出处】是不能修改的。那么有什么办法来控制呢?通本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。过一个判断,判断是否已经存在同名的 ob【转载请注明来源】【未经授权禁止转载】jectStore 即可。

未经授权,禁止复制转载。【原创不易,请尊重版权】原创内容,盗版必究。
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 不会在每【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。次刷新页面的时候执行,而是在刷新页面时,【作者:唐霜】未经授权,禁止复制转载。indexedDB 发现 version著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net 被升级了的时候执行。因此,所有的数据库【本文首发于唐霜的博客】【本文首发于唐霜的博客】结构的东西,都要放在这个函数内去做。

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

objectStore 创建之后不可修改【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net,如果创建时失误,给了错误的配置,必须先本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。删除该 objectStore 之后,重原创内容,盗版必究。【原创不易,请尊重版权】新创建。

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

objectStore 的类型

在编程上,不需要去分 objectSto【作者:唐霜】著作权归作者所有,禁止商业用途转载。re 的类型。但是,在我们实际存储数据的【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。时候,我们自己需要去区分,因为不同类型的【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。 objectStore 用法不同。

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

对象型仓库

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

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

这里的对象不包括数组。

【转载请注明来源】【原创内容,转载请注明出处】【版权所有,侵权必究】【原创内容,转载请注明出处】
db.createObjectStore('mystore', { keyPath: 'id' })

非对象型仓库

如果一个 objectStore 是用来原创内容,盗版必究。【原创内容,转载请注明出处】存非对象的,例如我们经常会考虑用来存 A【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】rrayBuffer,这个时候,你应该在【未经授权禁止转载】【版权所有,侵权必究】创建 objectStore 的时候,传原创内容,盗版必究。【未经授权禁止转载】入配置信息 autoIncrement 本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】为 true,不传 keyPath。

转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。
db.createObjectStore('mystore', { autoIncrement: true })

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

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

混合仓库

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

转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】
db.createObjectStore('mystore', { keyPath: 'id', autoIncrement: true })

当你插入的对象中不存在 id 属性时,对【版权所有】唐霜 www.tangshuang.net【转载请注明来源】象会被污染,会自动加上 id 属性,并且【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】赋予一个数字作为 key。

原创内容,盗版必究。原创内容,盗版必究。转载请注明出处:www.tangshuang.net

什么是 autoIncrement?

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

【未经授权禁止转载】【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net

什么是自动生成?

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

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

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

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

著作权归作者所有,禁止商业用途转载。【转载请注明来源】本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。

index

索引是 indexedDB 中最值得玩味【关注微信公众号:wwwtangshuangnet】【本文受版权保护】的部分,这也是它取名“indexedDB本文作者:唐霜,转载请注明出处。【未经授权禁止转载】”的原因。索引,是一系列概念的统称:

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

简单的说,索引是独立于 objectSt原创内容,盗版必究。【原创不易,请尊重版权】ore 之外,但又和 objectSto【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。re 绑定的,用于建立更多查询线索的工具【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】

原创内容,盗版必究。【本文受版权保护】原创内容,盗版必究。本文作者:唐霜,转载请注明出处。

什么是 index?

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

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

未经授权,禁止复制转载。【本文首发于唐霜的博客】

上图是一个 index 存储器的示意图,【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net一个 objectStore 可以有多个【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】 index 和自己绑定。

原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。

index 和 objectStore 的关系

index 依附于 objectStor著作权归作者所有,禁止商业用途转载。【作者:唐霜】e。我们在创建索引时,首先要得到一个 o【原创不易,请尊重版权】原创内容,盗版必究。bjectStore,再在这个 obje本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】ctStore 的基础上创建一个索引。一【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】个 objectStore 可以有多个索【版权所有,侵权必究】【本文受版权保护】引。

【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。

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

本文版权归作者所有,未经授权不得转载。【本文受版权保护】【转载请注明来源】

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

index 实际上是对 objectSt【作者:唐霜】原创内容,盗版必究。ore 查询条件的补充。如果没有 ind转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】ex,我们只能通过 objectStor未经授权,禁止复制转载。原创内容,盗版必究。e 的 key 来查值,但是有了 ind【未经授权禁止转载】原创内容,盗版必究。ex,我们可以查询的能力被扩展到了任意属转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】性路径。

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

和 objectStore 不同,ind【版权所有,侵权必究】【版权所有,侵权必究】ex 的同一个 key 可以存在多个,因未经授权,禁止复制转载。【原创内容,转载请注明出处】为不同的存入值的某个 keyPath 可本文作者:唐霜,转载请注明出处。原创内容,盗版必究。能存在相同的值。

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

如何创建索引?

创建索引这个动作,实际上是对 objec著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。tStore 进行修改,因此,只能在 d未经授权,禁止复制转载。原创内容,盗版必究。b 的 onupgradeneeded 事件中处【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】理。

【版权所有】唐霜 www.tangshuang.net【本文受版权保护】【转载请注明来源】
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 方法,它可以创建索引【未经授权禁止转载】本文作者:唐霜,转载请注明出处。。它有三个参数,第一个参数是这个索引的 原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】indexName,第二个参数是 key转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】Path,第三个参数是 options,【本文受版权保护】本文作者:唐霜,转载请注明出处。其中 unique 选项被放在这里面。

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

如何修改索引?

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

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

索引的运行机制

indexName 是对一个索引的命名,本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。这个名字会被用在按索引检索中,它本身和使【转载请注明来源】【本文受版权保护】用被存储数据的那个属性路径没关系,但你可本文作者:唐霜,转载请注明出处。【未经授权禁止转载】以把它当做是一个别名。

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

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

【本文受版权保护】【版权所有,侵权必究】
objectStore.createIndex('indexName', 'index.keyPath', { unique: false })

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

著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】
const request = objectStore.index('indexName').get('indexKey')

这实际上是两个过程,第一个过程是在保存数原创内容,盗版必究。【作者:唐霜】据时(包括创建和更新),索引区会同步更新【关注微信公众号:wwwtangshuangnet】本文作者:唐霜,转载请注明出处。自己的 key,它包含如下步骤:

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

第二个过程是查询过程,.index('indexName') 这个动作就是从名字为 indexNam本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】e 的索引区去进行索引查询,.get('indexKey') 这个动作包含了好几步:

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

从某种意义上讲,索引查询的性能肯定不如直本文版权归作者所有,未经授权不得转载。【转载请注明来源】接通过 objectStore 的 ke未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。y 查询。

本文作者:唐霜,转载请注明出处。原创内容,盗版必究。【未经授权禁止转载】【本文受版权保护】

[1] 在索引中,存在一个叫 referenced value 的东西,即一个索引建立的时候,会自动引【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。用 objectStore 中对应的记录本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】。所以,对于开发者,不用担心索引是如何去【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。快速找到它在 objectStore 的【转载请注明来源】本文版权归作者所有,未经授权不得转载。对应记录的。

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

什么是 unique?

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

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

transaction

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

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

什么是 transaction?

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

未经授权,禁止复制转载。【本文首发于唐霜的博客】【本文首发于唐霜的博客】

特别是写操作,事务通过尝试性写入完成第一【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net步更新,如果整个尝试过程没有出错,那么会本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。通过一个 commit 操作使得整个更新本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。生效。但是如果在尝试过程中出错了,就会进著作权归作者所有,禁止商业用途转载。【作者:唐霜】行一个 abort 操作,之前做过的尝试未经授权,禁止复制转载。未经授权,禁止复制转载。会直接被丢弃,数据不会发生改变。一个 o【未经授权禁止转载】【转载请注明来源】bjectStore 的写入过程中,另外【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net一个写入操作会被挂起,直到上一个事务完成著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】

【本文首发于唐霜的博客】【转载请注明来源】【作者:唐霜】

如何使用 transaction?

在代码层面,我们必须通过 transac【本文受版权保护】原创内容,盗版必究。tion 方法,向数据库容器提出事务要求【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。,才能往具体的 objectStore 【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】进行数据处理:

【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】【转载请注明来源】
let transaction = db.transaction(['myObjectStore'], 'readonly')
let objectStore = transaction.objectStore('myObjectStore')
let request = objectStore.get('111')

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

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

transaction 方法有两个参数:

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

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

【本文首发于唐霜的博客】【作者:唐霜】

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

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

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

原创内容,盗版必究。转载请注明出处:www.tangshuang.net【转载请注明来源】
【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】

事务生命周期

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

【关注微信公众号:wwwtangshuangnet】【本文受版权保护】未经授权,禁止复制转载。

举一个错误的例子:

【版权所有】唐霜 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 中,事务会在非本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】常短的时间里面循环检查自己,当发现自己内转载请注明出处:www.tangshuang.net原创内容,盗版必究。部已经没有任何任务要做的时候,就将自己关【作者:唐霜】转载请注明出处:www.tangshuang.net闭。要深入了解这一点,你需要了解 jav转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】ascript 调用栈、事件循环的知识,【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net可能有点复杂。

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

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

未经授权,禁止复制转载。【版权所有】唐霜 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著作权归作者所有,禁止商业用途转载。据库读写的可用和安全。但是,真正涉及到如【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】何去存取数据,我们需要发起一个 requ【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.netest。一个事务过程中,可以有多个 re【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。quest,request 一定存在与事【原创内容,转载请注明出处】未经授权,禁止复制转载。务中,因此它肯定会有一个 transac【作者:唐霜】本文作者:唐霜,转载请注明出处。tion 属性来获取它所属于的那个事务的【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】容器。

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

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

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

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

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

目前,在 indexedDB 中,有四种【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。可能产生 request:open da【本文首发于唐霜的博客】原创内容,盗版必究。tabase,objectStore r【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。equest, cursor reque未经授权,禁止复制转载。【本文首发于唐霜的博客】st, index request。

本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。

cursor

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

【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】

什么是 cursor?

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

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

获取全部 object

想要获取一个 objectStore 中未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net的全部 object 可不是一件简单的事【作者:唐霜】本文版权归作者所有,未经授权不得转载。。indexedDB 1.0 版本的时候著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】没有直接提供类似的方法来获取(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 事件中,【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】如果 cursor 没有遍历完所记录,那【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】么通过执行 cursor.continu原创内容,盗版必究。【未经授权禁止转载】e() 来让游标滑动到下一个记录,ons【版权所有】唐霜 www.tangshuang.net【转载请注明来源】ucess 会被再次触发。而如果所有记录【原创内容,转载请注明出处】【未经授权禁止转载】都遍历完了,cursor 变量会是 un【原创内容,转载请注明出处】【原创内容,转载请注明出处】defined。

本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】【本文受版权保护】【转载请注明来源】

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

【原创内容,转载请注明出处】【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。

通过 index 查询集合

前文举例过如何通过 index 查询值。本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】但是,在前面的演示代码中,仍然只能得到一原创内容,盗版必究。【原创内容,转载请注明出处】个值,加入我们希望通过 index 得到【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。某个 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。

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

你也可以总结出游标的使用,简单的说,就是转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。对已知的集合对象(比如 objectSt著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。ore 或 index)进行遍历,在 o【原创不易,请尊重版权】未经授权,禁止复制转载。nsuccess 中使用 continu【原创不易,请尊重版权】【作者:唐霜】e 来进行控制。

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

数据的存取

当一个事务开始之后,在它的生命周期以内,【版权所有】唐霜 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转载请注明出处:www.tangshuang.net操作是很麻烦的,上面代码中我们使用了ge本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】t方法获取主键值为100001的obje著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.netct,但是获取过程是一个Request,本文版权归作者所有,未经授权不得转载。【作者:唐霜】后文会详细讲Request是什么东东,只【未经授权禁止转载】【原创内容,转载请注明出处】有在其onsuccess事件中才能得到获【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net取到的结果。

原创内容,盗版必究。【作者:唐霜】【版权所有】唐霜 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有限制,它的主转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net键值,也就是id值,不能是已存在的,如果【本文受版权保护】著作权归作者所有,禁止商业用途转载。objectStore中已经有了这个id著作权归作者所有,禁止商业用途转载。【作者:唐霜】,那么会报错。因此,在某些程序中,为了避本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net免这种情况的发生,我们使用put方法。

【转载请注明来源】【本文受版权保护】原创内容,盗版必究。

更新数据

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

【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net【转载请注明来源】

删除数据

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

delete方法把你传入的主键值对应的o【作者:唐霜】【原创内容,转载请注明出处】bject从数据库中删除。

【本文受版权保护】【关注微信公众号:wwwtangshuangnet】【原创内容,转载请注明出处】【未经授权禁止转载】

IndexedDB API

本节主要把indexedDB中最常用的所转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】有api进行列举,起到快速查阅的作用。注【作者:唐霜】本文版权归作者所有,未经授权不得转载。意,这里仅是最常用,基本可以覆盖90%的【版权所有,侵权必究】转载请注明出处:www.tangshuang.net使用场景,但并不代表所有的api都在这里【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。,你可以通过这里查阅全部。

原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。本文作者:唐霜,转载请注明出处。

IDBDatabase

也就是本文最开始使用open打开inde【原创不易,请尊重版权】【转载请注明来源】xedBD得到的db对象db,通过这节,了解这个idb有些什么接口可本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net以被调用。

【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】
let request = indexedDB.open(name, version)
request.onsuccess = (e) => {
  let db = e.target.result // 获得db
}

name

通过idb.name获取当前连接到的数据【原创内容,转载请注明出处】【未经授权禁止转载】库的名字。这和你在open的时候传入的n本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】ame是一致的。

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

version

和你在open的时候传入的version【作者:唐霜】本文作者:唐霜,转载请注明出处。是一致的。

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

objectStoreNames

获取当前数据库的所有objectStor【作者:唐霜】未经授权,禁止复制转载。e的name列表,是一个数组。

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

createObjectStore()

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

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

例子:

【本文受版权保护】【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】
db.createObjectStore('students', { keyPaht: 'id', autoIncrement: false })

deleteObjectStore()

删除一个objectStore,参数只有【关注微信公众号:wwwtangshuangnet】【版权所有,侵权必究】一个:

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

删除的时候,它的所有index也被删除了【版权所有】唐霜 www.tangshuang.net【作者:唐霜】

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

close()

关闭当前打开的这个数据库。关闭之后,任何【作者:唐霜】【未经授权禁止转载】操作都会报错。

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

transaction()

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

著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】

它有两个参数:

【未经授权禁止转载】转载请注明出处:www.tangshuang.net

我们用代码来看下用法:

【原创内容,转载请注明出处】【未经授权禁止转载】未经授权,禁止复制转载。
let tx = idb.transaction(['students'], 'readonly')

这样就获得了一个database的事务容著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。器。

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

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

未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。

IDBTransaction

关于transaction的概念前面已经著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。说了,这里主要看下,得到一个transa【未经授权禁止转载】未经授权,禁止复制转载。ction之后可以干什么。

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

db

获取这个transaction是对哪个d【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】atabase进行操作的事务。

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

objectStoreNames

这个事务要对哪些objectStore进未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net行操作,和你传入的objectStore未经授权,禁止复制转载。转载请注明出处:www.tangshuang.netNames是一致的,是一个数组。

【本文受版权保护】原创内容,盗版必究。

mode

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

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

abort()

终止该事务,一旦人为终止,你程序中的某些【未经授权禁止转载】本文作者:唐霜,转载请注明出处。操作就不会再执行了。

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

objectStore()

获取事务中的某个objectStore的【版权所有,侵权必究】未经授权,禁止复制转载。容器。它有一个参数:

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

获得该objectStore容器之后,就【版权所有,侵权必究】未经授权,禁止复制转载。可以利用它进行objectStore的数【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net据增删改查了。

【版权所有,侵权必究】【本文受版权保护】
let tx = idb.transaction(['students'], 'readonly')
let objStore = tx.objectStore('students')

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

注意,它的参数必须是在transacti【原创内容,转载请注明出处】【转载请注明来源】on的第一个参数数组中的。

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

IDBObjectStore

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

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

name

获取该objectStore的name。原创内容,盗版必究。未经授权,禁止复制转载。和创建的时候传入的name一致。

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

keyPath

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

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

autoIncrement

和创建的时候传入的autoIncreme【版权所有,侵权必究】【未经授权禁止转载】nt一致。

【转载请注明来源】【本文首发于唐霜的博客】

indexNames

获取该objectStore的所有索引的【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。命名列表,和createIndex传入的转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net第一个参数一致。

【未经授权禁止转载】【原创内容,转载请注明出处】【版权所有,侵权必究】

transaction

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

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

get()

发起一个获取object的Request【原创不易,请尊重版权】【原创内容,转载请注明出处】。Request我们还没有讲到,后面会讲未经授权,禁止复制转载。【本文首发于唐霜的博客】。它有一个参数:

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

代码说话:

原创内容,盗版必究。【未经授权禁止转载】
let objStore = tx.objectStore('students')
let request = objStore.get(100001)

而要得到最后查询到的object,需要在本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】request的onsuccess中获取【作者:唐霜】原创内容,盗版必究。。所以后面讲完Request之后,你就能著作权归作者所有,禁止商业用途转载。【转载请注明来源】正确使用代码了。

【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。未经授权,禁止复制转载。【转载请注明来源】

add()

发起一个添加object的Request本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。。它有一个参数:

【版权所有,侵权必究】【原创不易,请尊重版权】

还是用代码来看下:

转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net
let objStore = tx.objectStore('students')
let request = objStore.add({
  id: '100002',
  name: 'Li Hua',
})

delete()

发起一个删除object的Request转载请注明出处:www.tangshuang.net【本文受版权保护】。它有一个参数:

【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】【本文首发于唐霜的博客】【本文首发于唐霜的博客】

put()

发起一个更新某个object的Reque【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】st。它有两个参数:

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

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

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

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

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

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

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

如果你还有不理解的地方,欢迎在下方留言,【转载请注明来源】【未经授权禁止转载】对这个问题进行探讨。

【本文受版权保护】著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】【未经授权禁止转载】

count()

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

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

clear()

没有参数,发起一个删除objectSto本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】re里面的所有object的Reques本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】t。

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

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

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

openCursor()

发起一个打开游标的Request。它的参【转载请注明来源】【版权所有】唐霜 www.tangshuang.net数统一在IDBCursor中讲。

【本文受版权保护】转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。

index()

通过index方法,可以建立一个类似SQ未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.netL数据库中视图。它先得到一个IDBInd【未经授权禁止转载】【本文受版权保护】ex,然后你在对这个IDBIndex进行【转载请注明来源】著作权归作者所有,禁止商业用途转载。操作。因此它不是发起一个Request,【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】这有别于前面的方法。返回的IDBInde【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】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()

创建一个索引,和前面的方法不同,它不是发【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net起一个Request,而是直接进行操作,【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。并且返回一个IDBIndex。关于IDB【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.netIndex,我会在Request后面再讲著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】。它有三个参数:

本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】

虽然objectParameters还有转载请注明出处:www.tangshuang.net原创内容,盗版必究。其他选项,但是常用的就是unique。

【未经授权禁止转载】转载请注明出处:www.tangshuang.net

注意,只能在onupgradeneede【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】d中使用。

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

deleteIndex()

删除一个索引,也不用发起Request。转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net它有一个参数:

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

删除索引之后,就不能再根据索引查询数据了本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】

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

另外需要注意,创建和删除索引,都需要在打【关注微信公众号:wwwtangshuangnet】【作者:唐霜】开db的Request的onupgrad未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。eneeded事件中完成。

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

IDBRequest

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

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

目前,在indexedDB中,有四种可能转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。产生Request:open datab【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.netase,objectStore requ【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】est, cursor request,【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。 index request。

【本文首发于唐霜的博客】未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net

readyState

Request的状态。只有两种状态:pe【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。nding, done。

【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。

transaction

获取该Request所属于的transa【作者:唐霜】著作权归作者所有,禁止商业用途转载。ction。

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

source

获取该Request是由谁发起的,它可能【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。有四种情况:objStore, curs本文作者:唐霜,转载请注明出处。原创内容,盗版必究。or, index, null. 当该R【转载请注明来源】【原创不易,请尊重版权】equest是open database转载请注明出处:www.tangshuang.net【未经授权禁止转载】的时候发起,source值为null。

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

通过该source值,其实可以获取更多信【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。息,比如objectStore的其他信息原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】

【本文首发于唐霜的博客】【版权所有,侵权必究】【作者:唐霜】

result

获取该Request的输出结果。该值最开原创内容,盗版必究。【未经授权禁止转载】始是undefined,只有当Reque【转载请注明来源】【未经授权禁止转载】st成功之后,该值才会出现。因此,要获取本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】一个get的最终结果,必须在Reques本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.nett的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本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】方法时,前文在讲IDBObjectSto【版权所有,侵权必究】转载请注明出处:www.tangshuang.netre的时候已经讲到过了。

【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。原创内容,盗版必究。
let objStore = tx.objectStore('students')
let objIndex = objStore.index('name')

通过index方法之后,这个objInd【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】ex可以进行哪些操作呢?

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

name

该属性可以获取index的name。

【作者:唐霜】【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】

keyPath

该属性可以获取index的keyPath著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】,也就是object的某个属性的名字。这未经授权,禁止复制转载。【本文首发于唐霜的博客】个你在createIndex的时候传入的著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。keyPath是一致的。

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

unique

返回是否是唯一的,和你createInd本文作者:唐霜,转载请注明出处。原创内容,盗版必究。ex的时候传入的值是一致的。

【未经授权禁止转载】转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】

isAutoLocale

返回一个boolean值,它表示这个in本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。dex是否是自增的,和前面的autoIn【版权所有,侵权必究】【未经授权禁止转载】crement有关。

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

locale

如果这个index对应的字段是自增的,那【原创内容,转载请注明出处】原创内容,盗版必究。么现在的自增基础值是多少?比如你的id是转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net自增的,现在objectStore里面有转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】10个object,这时objIndex【未经授权禁止转载】原创内容,盗版必究。.locale应该是10.

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

objectStore

因为IDBIndex总是通过object【版权所有】唐霜 www.tangshuang.net【作者:唐霜】Store的index方法产生的,所以它【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】自然会有对应的那个objectStore【原创内容,转载请注明出处】【原创内容,转载请注明出处】,而自己的objectStore属性正好本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。是一个引用,指向那个产生自己的objec转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】tStore。

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

count()

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

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

get()

发起一个从当前index获取一个值为传入【转载请注明来源】本文作者:唐霜,转载请注明出处。参数的object的Request。它有未经授权,禁止复制转载。【作者:唐霜】一个参数:

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

这里的key有点难理解,前面object原创内容,盗版必究。【本文首发于唐霜的博客】Store的get方法传入的是主键的值,本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】而这类的get传入的是你选择的这个索引对原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net应的属性的值。比如说:

著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。【转载请注明来源】未经授权,禁止复制转载。
{
  id: 1,
  name: 'tom',
}

id是主键,name是一个索引。那么这个【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net时候,如果你想得到这个object,应该【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。使用:

【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net
let request = objIndex.get('tom') // 这个tom是name属性的值

openCursor()

发起一个打开游标的Request。它的参【原创不易,请尊重版权】【原创内容,转载请注明出处】数统一在IDBCursor中讲。

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

可以看出,objIndex对于objSt【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】ore而言,方法少了很多,它不能更新、删原创内容,盗版必究。【未经授权禁止转载】除等。但是实际上,通过objectSto【作者:唐霜】未经授权,禁止复制转载。re属性,就可以反过来对objectSt【转载请注明来源】【版权所有,侵权必究】ore进行操作。

【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】【原创不易,请尊重版权】

IDBCursor

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

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

但是在开始之前,你要回头看下游标是怎么得【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。到的?

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

openCursor()

objectStore或objectIn【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】dex可以使用这个方法打开一个游标的Re原创内容,盗版必究。【转载请注明来源】quest。它有两个参数:

转载请注明出处:www.tangshuang.net【转载请注明来源】

打开游标后,游标怎么获得呢?在Reque未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。st的onsuccess中得到的:

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

接下来就是看看,这个cursor有哪些接【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net口。

【本文首发于唐霜的博客】【版权所有,侵权必究】

direction

游标遍历的方向,方向前面说过了,和你op著作权归作者所有,禁止商业用途转载。【转载请注明来源】enCursor的时候传入的是一致的。

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

key

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

【原创不易,请尊重版权】【转载请注明来源】
{
  id: 2,
  name: 'sue',
}

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

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

primaryKey

游标遍历所在位置的object的主键。这本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。个比较难理解,key和primaryKe【本文受版权保护】本文版权归作者所有,未经授权不得转载。y的区别主要体现在你用索引进行检索的时候未经授权,禁止复制转载。【未经授权禁止转载】,如果你openCursor是在非索引集【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net合情况下,其实key和primaryKe本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.nety是一样的,因为都是以主键作为索引。但是【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。当你用index方法筛选出子集,那么这个【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。时候primaryKey在某些情况下就非本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】常有必要知道。

【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。

source

该属性返回开启游标的容器的引用,也就是o本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】bjStore或objIndex。

【本文受版权保护】本文作者:唐霜,转载请注明出处。原创内容,盗版必究。本文作者:唐霜,转载请注明出处。

value

改属性返回当前遍历到的object,严格【版权所有,侵权必究】【原创不易,请尊重版权】的说,这个属性是IDBCursorWithValue的属性。

【本文受版权保护】【本文受版权保护】

continue()

游标往下移动一格或移动到你规定的位置。注【原创不易,请尊重版权】未经授权,禁止复制转载。意,它是根据你规定的方向进行移动的。它可【原创内容,转载请注明出处】【作者:唐霜】以有一个参数:

【原创不易,请尊重版权】未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】

advance()

continue()是只移动一格,adv本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.netance()可以自己规定移动的格数。它有本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。一个参数:

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

continuePrimaryKey()

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

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

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

【原创内容,转载请注明出处】【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net

delete()

发起一个删除当前游标所在的object的【转载请注明来源】未经授权,禁止复制转载。Request。删除之后,就要考虑用co【转载请注明来源】著作权归作者所有,禁止商业用途转载。ntinuePrimaryKey(),而转载请注明出处:www.tangshuang.net【本文受版权保护】不是continue()。

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

update()

发起一个更新当前游标所在的这个objec本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。t的对应字段的值的Request。它有一著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net个参数:

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

小结

本文所有的内容就讲完了,本文从 Inde【原创内容,转载请注明出处】【本文首发于唐霜的博客】xedDB 的概念和结构开始,把所有常用本文作者:唐霜,转载请注明出处。【本文受版权保护】的 API 都讲了一遍,并且还给出了很多【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】例子。
著作权归作者所有,禁止商业用途转载。 有人做过一个预测,Web SQL 数据【转载请注明来源】原创内容,盗版必究。库已经从标准中移除了,有可能在后面的浏览【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。器版本中被去除,IndexedDB 将有著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】可能统一浏览器本地化存储的数据库。

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

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

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

参考文献

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

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

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

      谢谢提醒