IndexedDB是浏览器提供的本地数据库,它可以被网页脚本创建和操作。IndexedDB 允许储存大量数据,提供查找接口,还能建立索引。就数据库类型而言,IndexedDB是非关系型数据库(不支持 SQL 查询语句),更接近NoSQL数据库,并且Web Worker中可用。

IndexedDB的特点

  1. 键值对储存:IndexedDB内部采用对象仓库(object store)存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象。对象仓库中,数据以"键值对"的形式保存,每一个数据记录都有对应的主键,主键是独一无二的,不能有重复,否则会抛出一个错误。
  2. 异步:不同于LocalStorage,IndexedDB操作是异步的。异步设计是为了防止大量数据的读写时浏览器卡死。
  3. 支持事务:IndexedDB支持事(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。
  4. 同源限制:IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
  5. 储存空间大:IndexedDB的储存空间非常大。
  6. 支持二进制储存:IndexedDB不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)。

存储限制

浏览器的最大存储空间是动态的,取决于硬盘大小。全局限制为可用磁盘空间的50%。假设可用硬盘驱动器是500GB,那么浏览器的总存储容量为250GB。如果超过此范围,则会发起称为源回收的过程,删除整个源的数据,直到存储量再次低于限制。删除源数据没有只删一部分的说法——因为这样可能会导致不一致的问题。

还有另一个限制称为组限制(全局限制的20%)。最小组限制为10MB,但组限制不能超过全局限制,因此如果内存非常低,比如全局限制为8MB,则组限制也将为8MB。最大组限制为2GB。 每个源都是一组(源组)的一部分,每个顶级域名都有一个组,每个子域名都有一个源。

在隐私浏览模式下,大多数数据存储不被支持。本地存储数据和cookie仍然可用,但它们是短暂的,当关闭最后一个隐私浏览窗口时,数据将被删除。

Chrome Internet Explorer Firefox Safari
允许浏览器使用多达80%的总磁盘空间。一个来源最多可以使用总磁盘空间的 60%。其他基于 Chromium 的浏览器可能允许浏览器使用更多的存储空间。 Internet Explorer 10 及更高版本最多可以存储250MB,并且在使用量超过10MB时会提示用户 允许浏览器使用多达50%的可用磁盘空间,每个源组最多可以使用2GB。 允许 1GB 左右。当达到限制时,Safari会提示用户,同时以200MB的增量增加限制。

使用StorageManager API可以查询可用存储量及其目前使用的存储量,它会报告 IndexedDB和缓存API使用的总字节数,还可以计算近似的可用剩余存储空间。Chrome 则会始终报告实际磁盘大小的60%,其他基于 Chromium的浏览器在报告可用配额时可能会考虑可用空间量。

if (navigator.storage && navigator.storage.estimate) {const quota = await navigator.storage.estimate();// quota.usage -> 已用字节数。// quota.quota -> 最大可用字节数。const percentageUsed = (quota.usage / quota.quota) * 100;console.log(`您已使用可用存储的 ${percentageUsed}%。`);const remaining = quota.quota - quota.usage;console.log(`您最多可以再写入 ${remaining} 个字节。`);
}

StorageManager并不是所有浏览器都支持。

打开数据库

使用indexedDB.open打开数据库,open方法返回一个IDBOpenDBRequest对象,同时这是一个异步操作,open操作并不会立马打开数据库或者开启事务,我们可以通过监听request的事件来进行相应的处理。如果要打开的数据库不存在,浏览器会自动创建。

open方法传入两个参数,第一个参数是数据库的名字,第二个参数是数据库的版本号。

当创建一个新的数据库或者升级一个现有的数据库版本的时候,将会触发一个onupgradeneeded事件,并在事件中传入IDBVersionChangeEvent,我们可以通过event.target.result来获取到IDBDatabase对象,然后通过这个对象来进行数据库的版本升级操作。

const version = 1; // 版本主要用来控制数据库的结构,当数据库结构(表结构)发生变化时,版本也会变化
const dbName = "myData";
const request = window.indexedDB.open(dbName, version);let db; // 全局 IndexedDB 数据库实例// onupgradeneeded 在版本改变时触发(首次连接数据库时,版本从 0 变成 1,因此也会触发,且先于 onsuccess)
request.onupgradeneeded = (event) => {db = event.target.result;
};// onsuccess 在连接成功后触发
request.onsuccess =  (event) => {db = request.result;console.log("db connected");
};// onerror 在连接失败时触发
request.onblocked =  (event) => {console.log("db request blocked!");
}// onblocked 在连接被阻止的时候触发,比如打开版本低于当前存在的版本
request.onerror =  (event) => {console.log("error!");
};

创建数据表

主键(key)是默认建立索引的属性,既可以让IndexedDB自动生成主键,也可以使用数据记录里面合适的属性作为主键。比如,数据记录是{ id: 1, name: ‘张三’ },那么id属性可以作为主键。主键也可以指定为下一层对象的属性,比如{ foo: { bar: ‘baz’ } }的foo.bar也可以指定为主键。

request.onupgradeneeded = (event) => {const db = event.target.result;if (!db.objectStoreNames.contains("person")) {// 创建数据表并设置id为自增主键db.createObjectStore("person", {"keyPath": "id", // 主键"autoIncrement": true // 自增(每加一条数据,主键会自动增长,无需开发者指定)});}
};

添加数据

在indexedDB里任何的存取对象的操作都需要放在事务里执行。为了往数据库里新增数据,我们首先需要创建一个事务,新建时必须指定表格名称和操作模式(读写权限)。

新建事务以后,通过IDBTransaction.objectStore(name)方法,拿到 IDBObjectStore 对象,再通过表格对象的add()方法,向表格写入一条记录。

写入操作是一个异步操作,通过监听连接对象的success事件和error事件,了解是否写入成功。

const transaction = db.transaction(["person"], "readwrite"); // 创建事务
const objectStore = transaction.objectStore("person"); // 指定person表
objectStore.add({ "name": "张三", "age": 24, "email": "zhangsan@example.com"
}); // 添加数据transaction.oncomplete = (event) => {console.log("数据写入成功");
};transaction.onerror = (event) => {console.log("数据写入失败");
};

获取数据

读取数据也是通过事务完成,需要先创建一个readonly的Transaction,通过IDBTransaction.objectStore(name)方法,拿到IDBObjectStore 对象,再通过表格对象的get()方法读取数据,参数是主键的值。

const transaction = db.transaction(["person"], "readonly");
const objectStore = transaction.objectStore("person");
const request = objectStore.get(1);request.onerror = (event) => {console.log("事务失败");
};request.onsuccess = (event) => {const result = event.target.result;if (result) {console.log("Name: " + result.name);console.log("Age: " + result.age);console.log("Email: " + result.email);} else {console.log("未获得数据记录");}
};

遍历数据

遍历数据表格的所有记录,要使用指针对象IDBCursor。

const transaction = db.transaction(["person"], "readonly");
const objectStore = transaction.objectStore("person");
const request = objectStore.openCursor();// penCursor()方法是一个异步操作,要监听success事件
request.onsuccess = (event) => {const cursor = event.target.result;if (cursor) {console.log("Id: " + cursor.key);console.log("Name: " + cursor.value.name);console.log("Age: " + cursor.value.age);console.log("Email: " + cursor.value.email);cursor.continue()} else {console.log("没有更多数据了!");}
};

更新数据

更新数据要使用IDBObject.put()方法。

const transaction = db.transaction(["person"], "readwrite");
const objectStore = transaction.objectStore("person");
const request = objectStore.put({"id": 1,"name": "李四", "age:" 35, "email": "lisi@example.com"
}); // put()方法自动更新了主键为1的记录request.onerror = (event) => {console.log("数据更新失败");
};request.onsuccess = (event) => {console.log("数据更新成功");
};

删除数据

IDBObjectStore.delete()方法用于删除记录。

const transaction = db.transaction(["person"], "readwrite");
const objectStore = transaction.objectStore("person");
const request = objectStore.delete(1);request.onerror = (event) => {console.log("数据删除失败");
};request.onsuccess = (event) => {console.log("数据删除成功");
};

新建索引

IDBObject.createIndex()的三个参数分别为索引名称、索引所在的属性、配置对象(说明该属性是否包含重复的值)

request.onupgradeneeded = (event) => {const db = event.target.result;if (!db.objectStoreNames.contains("person")) {// 创建数据表并设置id为自增主键const objectStore = db.createObjectStore("person", {"keyPath": "id", // 主键"autoIncrement": true // 自增(每加一条数据,主键会自动增长,无需开发者指定)});// 新建对象仓库以后,下一步可以新建索引objectStore.createIndex("name", "name", { "unique": false });objectStore.createIndex("email", "email", { "unique": true });}
});

查询索引

索引的意义在于,可以让你搜索任意字段,也就是说从任意字段拿到数据记录。如果不建立索引,默认只能搜索主键(即从主键取值)。

const transaction = db.transaction(["person"], "readonly");
const objectStore = transaction.objectStore("person");
const index = objectStore.index("name");
const request = index.get("李四");request.onerror = (event) => {console.log("数据查询失败");
};request.onsuccess = (event) => {const result = event.target.result;if (result) {console.log("Name: " + result.name);console.log("Age: " + result.age);console.log("Email: " + result.email);} else {console.log("未获得数据记录");}
};

删除数据库

indexedDB.deleteDatabase()方法用于删除一个数据库,参数为数据库的名字。它会立刻返回一个IDBOpenDBRequest对象,然后对数据库执行异步删除。删除操作的结果会通过事件通知,IDBOpenDBRequest对象可以监听以下事件。

const dbName = "myData";
const request = window.indexedDB.deleteDatabase(dbName);request.onerror = (event) => {console.log("删除失败");
};request.onsuccess = (event) => {console.log("删除成功");
};

相关库

  • Godb.js让你即使你不了解浏览器数据库sIndexedDB也能使用 ,从而把关注点放到业务上面去。
  • localForage一个简单的 Polyfill,提供了简单的客户端数据存储的值语法。它在后台使用IndexedDB,并在不支持 IndexedDB的浏览器中回退到WebSQL或localStorage。
  • Dexie.jsIndexedDB 的包装,通过简单的语法,可以更快地进行代码开发。
  • ZangoDB类似MongoDB的IndexedDB接口,支持MongoDB的大多数熟悉的过滤、投影、排序、更新和聚合功能。
  • JsStore一个带有SQL语法的IndexedDB包装器。
  • MiniMongo由localstorage支持的客户端内存中的mongodb,通过http进行服务器同步。MeteorJS使用MiniMongo。
  • PouchDB使用IndexedDB在浏览器中实现CouchDB的客户端。
  • idb一个微小的(~1.15k)库,大多API与IndexedDB类似,但做了一些小的改进,让数据库的可用性得到了大大的提升。
  • idb-keyval使用IndexedDB实现的超级简单且小巧的(~600B)基于Promise的键值对存储。
  • sifrr-storage一个非常小的(~2kB)基于Promise的客户端键值数据库。基于 IndexedDB、localStorage、WebSQL和Cookies 实现。它可以自动选择上述支持的数据库,并按照优先顺序使用。
  • lovefieldLovefield是一个用于Web App 的关系型数据库,使用JavaScript编写,可以在不同的浏览器环境中运行,提供了类似SQL的 API,速度快、安全且易用。

参考:IndexedDB API

初识IndexedDB本地存储相关推荐

  1. HTML5 API详解(18):IndexedDB 本地存储

    Web SQL Database实际上已经被废弃,而HTML5的支持的本地存储实际上变成了Local Storage和Session Storage与IndexedDB.Web Storage使用简单 ...

  2. Chrome 下IndexedDB 本地存储

    一.概论 IndexedDB 就是浏览器提供的本地数据库,它可以被网页脚本创建喝操作.IndexedDB 允许存储大量数据,提供查找接口,还能建立索引.就数据库类型而言,IndexedDB 是非关系型 ...

  3. HTML5 IndexedDB本地存储介绍

    在开始介绍IndexedDB之前我先简单说一下Web SQL Database 一.indexedDB为何替代了Web SQL Database? 跟小朋友的教育从来没有什么"赢在起跑线&q ...

  4. HTML5本地存储IndexedDB基础使用

    做项目时需要用H5本地存储,感觉还不错 下面是一些基础知识和一个完整的实例 HTML5 的一个重要特性是本地数据持久性,它使用户能够在线和离线访问 Web 应用程序.此外,本地数据持久性使移动应用程序 ...

  5. HTML5本地存储——IndexedDB(二:索引)

    在HTML5本地存储--IndexedDB(一:基本使用)中介绍了关于IndexedDB的基本使用方法,很不过瘾,这篇我们来看看indexedDB的杀器--索引. 熟悉数据库的同学都知道索引的一个好处 ...

  6. HTML5本地存储——IndexedDB

    在HTML5本地存储--Web SQL Database提到过Web SQL Database实际上已经被废弃,而HTML5的支持的本地存储实际上变成了 Web Storage(Local Stora ...

  7. 本地存储-cookie|localStorage|sessionStorage|indexedDB

    本地存储 本地存储 cookie 如何工作 问题 cookie标准限制 属性 expires|max-age domain&path secure HttpOnly 设置cookie 服务端设 ...

  8. 前端三种本地存储方式+indexedDB浏览器数据库存储

    1.cookie存储: 特征:1.不同的浏览器存放的cookie位置不一样,也是不能通用的.2.cookie的存储是以域名形式进行区分的,不同的域下存储的cookie是独立的.3.我们可以设置cook ...

  9. IndexedDB浏览器本地存储、缓存、数据库、介绍

    目录 1.前言 2.IndexedDB简介 3.IndexedDB使用场景 4.IndexedDB特点 4.1.非关系型数据库 NoSql 4.2.持久化存储 4.3.异步操作 4.4.支持事务 4. ...

最新文章

  1. 分享是程序员的必备素质
  2. 《JAVA练习题目7》 定义一个素数生成器类PrimeGenerator,用于生成给定区间内的所有素数。(类PrimeGenerator都由类Main代替)
  3. 还在熬夜憋思路?这12篇最新论文打包送给你 | 本周值得读
  4. Roller5.0.3安装配置部署 step by step
  5. JDK 9 –给圣诞老人的信?
  6. lighttpd,thttpd,shttpd - 轻量级WebServer介绍
  7. QT学习笔记:常用快捷键总结表
  8. 作者:李海昌(1984-),男,中国科学院软件研究所助理研究员
  9. 【血糖检测】基于matlab改进深度回归网络的无创血糖检测【含Matlab源码 1572期】
  10. IsPostBack深入探讨
  11. 阿里 Lindorm 数据库联手 Hightopo ,开启工业物联超融合存储模式
  12. 浙江高院:引导当事人用区块链存取证据,微版权提供一站式知识产权保护服务
  13. 基于SpringBoot+Vue的宠物商场管理系统
  14. 关于qq一键登录的一些问题
  15. 【毕业季·进击的技术er】这三年来的风风雨雨,喜怒哀乐,坎坎坷坷,朝朝暮暮……都是那么美好,那么令人难以忘记。
  16. Lingo的基础语法(一)
  17. 浮点数的整数小数部分分别输出
  18. 金蝶提示系统检测到服务器异常,金蝶提示连接云服务器异常
  19. 【Mac 环境配置】--安装git及使用
  20. ༺ཌ༈计算机科普༈ད༻

热门文章

  1. 人工智能数学基础训练营5周学习资料
  2. 涂书笔记-让读书笔记不再困难
  3. Head First C#中文版 图文皆译 (page13)
  4. 循环数142857问题 java_神奇数字142857与周期循环规律
  5. PS制作渐变金属文字
  6. 大数据必知必会之Kafka
  7. 打印杨辉三角 - C语言实现
  8. Java知识点全面汇总
  9. 工信部发证 中国广电成第四大基础电信运营商
  10. 安逸云中小云厂商机遇