目录

  • 简介
  • 无法开启indexDb的情况
  • 开始使用
    • 打开数据库
    • 为该数据库创建一个对象仓库
    • 新增数据
    • 查找数据
      • 使用索引查询
      • 使用游标查询
    • 修改数据
    • 删除数据
  • 简单封装
  • indexDB库

简介

IndexedDB 是一种可以让你在用户的浏览器内持久化存储数据的方法。IndexedDB 为生成 Web Application 提供了丰富的查询能力,使我们的应用在在线和离线时都可以正常工作。

无法开启indexDb的情况

  1. 浏览器不希望允许某些广告网络或恶意网站来污染你的计算机,所以浏览器会在任意给定的 web app 首次尝试打开一个 IndexedDB 存储时对用户进行提醒。用户可以选择允许访问或者拒绝访问。
  2. IndexedDB 在浏览器的隐私模式(Firefox 的 Private Browsing 模式和 Chrome 的 Incognito 模式)下是被完全禁止的。

开始使用

打开数据库

首先要判断浏览器是否支持支持indexDb,之后在打开,并生成错误处理函数

let indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
if (!indexedDB) {console.log("浏览器不支持indexedDB");
}
// 打开我们的数据库,使用open方法
let request = indexedDB.open("MyTestDatabase");
// 错误处理,onerror函数
request.onerror = function (event) {console.log("error", event);
};

为该数据库创建一个对象仓库

假设我们需要存储用户信息,信息格式为{id:1,name:"张三",email:"1@qq.com"}。那么我们吧仓库命名为"userInfo"
当你创建一个新的数据库或者增加已存在的数据库的版本号, onupgradeneeded 事件会被触发

// 接上面的代码
request.onupgradeneeded = function (event) {var db = event.target.result;// 为该数据库创建一个对象仓库,创建一个名为“userInfo”的仓库,并指定id作为键路径(keyPath)var objectStore = db.createObjectStore("userInfo", {keyPath: "id"});// 建立一个索引来通过姓名来搜索客户。名字可能会重复,所以我们不能使用 unique 索引objectStore.createIndex("name", "name", {unique: false});// 使用邮箱建立索引,我们向确保客户的邮箱不会重复,所以我们使用 unique 索引objectStore.createIndex("email", "email", {unique: true});
};

createObjectStore(name, options)函数接收两个参数,第一个参数为仓库的名字,第二个参数是个对象,是可选参数,其中包括以下的属性:

  1. keyPath:指定键路径,需要唯一,可以不指定
  2. autoIncrement:boolean类型,键生成器,是否自动生成,默认false

createIndex(name,keypath,options)接受三个参数
name:索引的名称,可为空
keypath:索引对应的keyPath
options:可选,参数为:

  1. unique:boolean类型,如果为 true,则索引将不允许单个键的重复值。
  2. multiEntry:boolean类型,如果true,则当keyPath解析为数组时,索引将在每个数组元素的索引中添加一个条目。如果 false,它将添加一个包含数组的条目。
  3. locale:目前仅限 Firefox (43+),为索引指定语言环境

新增数据

上面已经创建好数据库和表了,数据库名:MyTestDatabase,表名:userInfo,浏览器打开F12,Application->IndexDB即可看到,接下来我们为表中增加100条数据。
首先我们先自己造100条数据:

let arr = [];
for (let i = 0; i < 100; i++) {arr.push({id: i,name: "张" + i,email: i + "@qq.com"});
}

之后新增到userInfo表中:

request.onsuccess = function (event) {db = event.target.result;var transaction = db.transaction(["userInfo"], "readwrite");var objectStore = transaction.objectStore("userInfo");for (let i of arr) {objectStore.add(i);}
};

transaction(storeNames, mode, options)表示一个事务。在数据库上创建一个事务,指定作用域(例如要访问的存储对象),并确定所需的访问类型(只读或读写)。接收三个参数:
storeNames:字符串数组,对象库名称,如果只有一个,也可以写字符串不写数组
mode:字符串,可选参数。readonly和readwrite,默认为readonly,表示只读,readwrite表示可以写入。除此之外还有个只用于Firefox的“readwriteflush”,目前实验性的。
options:可选参数,durability: “default”, “strict”, 或 “relaxed”。默认值为"default"。"relaxed"提供了更好的性能,"relaxed"用于临时数据。

objectStore()表示允许访问通过主键查找的 IndexedDB 数据库中的一组数据的对象存储区。为了方便理解,可以把“对象存储空间”想象成关系数据库的“表”结构,下文也会把对象存储空间称为表。

查找数据

可以使用get方法查找到某一条数据

request.onsuccess = function (event) {db = event.target.result;var transaction = db.transaction(["userInfo"]);var objectStore = transaction.objectStore("userInfo");let men1 = objectStore.get(2);men1.onsuccess = function (e) {var data = e.target.result;console.log(data);};
};

使用索引查询

有时候我们并不能确定用户的id,只能通过其他方式去查找,比如我们想查找邮箱为"5@qq.com"的用户,这时候就需要用到索引。
使用索引之前必须确定已经设置了索引,在创建表的时候,我们通过 objectStore.createIndex("email", "email", {unique: true});设置了email的索引

request.onsuccess = function (event) {db = event.target.result;var transaction = db.transaction(["userInfo"]);var objectStore = transaction.objectStore("userInfo");let men1 = objectStore.index("email");// 查找邮箱为‘5@qq.com’的用户men1.get('5@qq.com').onsuccess = function (e) {var data = e.target.result;console.log(data);};
};

index()方法参考objectStore方法一览

使用游标查询

游标的使用方法:

request.onsuccess = function (event) {db = event.target.result;var transaction = db.transaction(["userInfo"]);var objectStore = transaction.objectStore("userInfo");let men1 = objectStore.openCursor();men1.onsuccess = function (e) {var data = e.target.result;if (data) {console.log(data.value);data.continue(); // 使游标下移} else {console.log("No more entries!");}};
};

如果我们要查询id 5-9的数据,不包含5,但包含9

    let men1 = objectStore.openCursor(IDBKeyRange.bound(5,9,true, false));let list=[]men1.onsuccess = function (e) {var data = e.target.result;if (data) {list.push(data.value)data.continue(); // 使游标下移} else {console.log("No more entries!");}console.log(list); // 打印出id是6 7 8 9的数据};

修改数据

使用get方法找到数据并指定为“readwrite”进行修改

request.onsuccess = function (event) {db = event.target.result;var transaction = db.transaction(["userInfo"], "readwrite");var objectStore = transaction.objectStore("userInfo");let men1 = objectStore.get(1);men1.onsuccess = function (e) {// 获取我们想要更新的数据var data = e.target.result;data.name="张三2"console.log(data)objectStore.put(data)};
};

删除数据

通过delete方法删除

request.onsuccess = function (event) {db = event.target.result;var transaction = db.transaction(["userInfo"], "readwrite");var objectStore = transaction.objectStore("userInfo");let men1 = objectStore.delete(1);men1.onsuccess = function (e) {console.log("删除成功")console.log( e)};
};

objectStore方法一览:

方法名 参数 作用
add(value,key) value:被存储的值.key:标识某条记录的键,如果不指定,它会被设为null 添加一条数据。
clear() 清除表
count(key) key:键或键范围(key range 计算符合条件的对象的数量
createIndex(name,keyPath,optional) *详见上方为该数据库创建一个对象仓库 创建并返回新的IDBIndex对象,该方法只能从versionchange事务模式的回调方法中被调用
delete(key) key:标识记录的键或键范围 从表中删除数据
deleteIndex(indexName) indexName:要删除的现有索引的名称 删除索引,该方法只能在VersionChange监听函数里面调用。
get(key) key:键或键范围 从表中检索请求的记录(只返回一条)
index(name) name:要打开的索引的名称 打开此表中的命名索引
openCursor(range,direction) range:用作游标范围的键范围。如果此参数未指定或为空,则该范围包括对象存储中的所有记录。direction:游标的方向,包括:“next”(显示所有记录,包括重复记录,从下往上移动),“nextunique”(显示所有记录,不包括重复项,从下往上移动),“prev”(显示所有记录,包括重复记录,从上往下移动),“prevunique”(显示所有记录,不包括重复记录,从上往下移动) 获取一个指针对象
openKeyCursor(range, direction) 同上 获取一个主键指针对象
put(value,key) value:新数据,key:主键,可为空 更新某个主键对应的数据记录,如果对应的键值不存在,则插入一条新的记录
getKey(key) key:主键值或 IDBKeyRange 对象 获取主键
getAll(query, count) query:键或IDBKeyRange,可选,count:返回值的数量,可选 获取对象仓库的记录
getAllKeys(query, coun) 同上 获取所有符合条件的主键

简单封装

原生的indexDB语法比较繁琐,把上面的代码稍微封装一下,方便调用

let indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;class DB {constructor(name, version, options) {this._dbs = {};this._databaseName = name;this.currentStore = "";this.open(name, version, options);}open(name, version, options) {if (!indexedDB) {console.error("浏览器不支持indexedDB");return;}return new Promise((resolve, reject) => {if (this._dbs && this._dbs[name]) {resolve(this._dbs[name]);return;}let request = indexedDB.open(name, version);request.onupgradeneeded = (event) => {let db = event.target.result;this._dbs[name] = db;for (let i in options) {// 判断是否存在表if (!db.objectStoreNames.contains(options[i].storeName)) {var objectStore = db.createObjectStore(options[i].storeName, options[i].option);for (let j of options[i].index) {objectStore.createIndex(j.name, j.keyPath, {unique: j.unique});}}}resolve(db);};request.onsuccess = (event) => {// IDBDatabaseconst db = event.target.result;// 缓存起来this._dbs[name] = db;resolve(db);};request.onerror = (event) => {reject(event);console.error('IndexedDB', event);};});}async _getTransaction(storeName, version) {let db;// 先从缓存获取if (this._dbs[this._databaseName]) {db = this._dbs[this._databaseName];} else {db = await this.open(this._databaseName, version);}return db.transaction([storeName], 'readwrite');}async _getObjectStore(storeName, version) {let transaction = await this._getTransaction(storeName, version);return transaction.objectStore(storeName);}// 获取一个storecollection(storeName, version) {this.currentStore = storeName;this._getObjectStore(storeName, version);return this;}add(data) {return new Promise((resolve, reject) => {this._getObjectStore(this.currentStore).then((objectStore) => {const request = objectStore.add(data);request.onsuccess = function (event) {resolve(event.target.result);};request.onerror = (event) => {reject(event);};});});}get(data) {return new Promise((resolve, reject) => {this._getObjectStore(this.currentStore).then((objectStore) => {const request = objectStore.get(data);request.onsuccess = function (event) {resolve(event.target.result);};request.onerror = (event) => {reject(event);};});});}delete(data) {return new Promise((resolve, reject) => {this._getObjectStore(this.currentStore).then((objectStore) => {const request = objectStore.delete(data);request.onsuccess = function (event) {resolve(event.target.result);};request.onerror = (event) => {reject(event);};});});}clear(data) {return new Promise((resolve, reject) => {this._getObjectStore(this.currentStore).then((objectStore) => {const request = objectStore.clear(data);request.onsuccess = function (event) {resolve(event.target.result);};request.onerror = (event) => {reject(event);};});});}put(data) {return new Promise((resolve, reject) => {this._getObjectStore(this.currentStore).then((objectStore) => {const request = objectStore.put(data);request.onsuccess = function (event) {resolve(event.target.result);};request.onerror = (event) => {reject(event);};});});}find(start,end,startInclude,endInclude){return new Promise((resolve, reject) => {this._getObjectStore(this.currentStore).then((objectStore) => {const request = objectStore.openCursor(IDBKeyRange.bound(start,end,startInclude, endInclude));request.onsuccess = function (event) {resolve(event.target.result);};request.onerror = (event) => {reject(event);};});});}// 还可以根据自己需求继续写
}

使用方法:

    let data = [];for (let i = 0; i < 100; i++) {data.push({id: i,name: "张" + i,email: i + "@qq.com"});}let option = [{storeName: "test1",option: {keyPath: "id"},index: [{name: 'id', keyPath: "id", unique: true}, {name: 'name', keyPath: "name", unique: false}, {name: 'emial', keyPath: "emial", unique: true}]}];let db = new DB("myTest", "1", option);const store = db.collection('test1',"1");store.add(data[0]);store.get(data[0].id).then((result) => {console.log(result);});store.add(data[1]);store.add(data[2]);store.delete(data[0].id)

indexDB库

在实际开发中我们可能更倾向于使用现成的轮子,比如

  1. dexie.js:IndexedDB 的包装,通过简单的语法,可以更快地进行代码开发。缺点是官方文档只有英文的
  2. IndexDBWrapper:有中文文档,对indexDB的简单封装,方法较少

大家可以根据实际需求选择自己封装还是直接使用现成的库。

indexDB的使用相关推荐

  1. 使用HTML5 IndexDB存储图像和文件

    使用IndexedDB存储图像和文件 有一天,我们写了关于如何在localStorage中保存图像和文件的文章,它是关于我们今天可用的实用主义. 然而,localStorage有一些性能影响 - 我们 ...

  2. 「工具」IndexDB 版备忘录

    前言 工作日常需要做一些备忘录,记录一些要做的事.在 Mac 上有使用系统的备忘录,但功能偏弱且文本格式调整不方便.再就是使用浏览器找专门的备忘录网站,功能是满足了,但是链路长,没有桌面软件直接. 所 ...

  3. 前端 IndexDB 操作入门教程

    前端 IndexDB 操作入门教程 idb-js 基于indexdb本地数据库的封装 文档地址 安装: npm install idb-js --save 使用: 第一步: 引入Idb import ...

  4. 前端存储之cookie、localStorage、sessionStorage、indexDB

    cookie Cookie 是小甜饼的意思.顾名思义,cookie 确实非常小,它的大小限制为4KB左右,是网景公司的前雇员 Lou Montulli 在1993年3月的发明.它的主要用途有保存登录信 ...

  5. 各种本地存储对比 cookie,localStorage,sessionStorage,indexDB以及他们和vuex的区别

    cookie 存储在cookie中的数据,每次都会被浏览器自动放在http请求中,如果这些数据并不是每个请求都需要发给服务端的数据,浏览器这设置自动处理无疑增加了网络开销:但如果这些数据是每个请求都需 ...

  6. 本地存储Cookie、Storage、indexDB、ServiceWork离线访问网站

    在日常开发中,开发者用得最多的大概是前三种吧,cookie.Session/Local,对后两种运用的较少,话不多少,直接正文: cookie cookie是客户端的解决方案,最早是网景公司的前雇员L ...

  7. VUE + idb-js 应用 indexDB

    装包 npm i idb-js 2023-6-13 , 优化一波使用 重新封装 table.js 在实际使用中, 发现, idb-js 不支持动态增加 表, 因此当存在多个项目使用同一套 代码时, 会 ...

  8. Cesium 使用 indexdb

    CesiumOfflineCache 这是一个 Cesium 插件,它使用 indexDB 离线缓存技术管理 影像图层.地形.3DTiles模型 等资源数据. https://github.com/W ...

  9. html5 indexdb api,html5 indexDB实例

    IndexedDB是用于客户端的大量的结构化数据存储和使用索引高效率搜索数据的API,它是基于W3C拟定的草案索引数据库的API.相对DOM存储的小存储数据量,IndexedDB具有大容量的数据存储功 ...

  10. php indexdb,前端存储 (4) - IndexDB

    IndexDB的出现 是为了存储更大量的结构化数据 简介 IndexedDB是一个事务型数据库系统,类似于基于SQL的RDBMS. 然而不同的是它使用固定列表(只有 key,value),Indexe ...

最新文章

  1. 线程安全(中)--彻底搞懂synchronized(从偏向锁到重量级锁)
  2. 从Docker 到Jenkins 到Ansible的部署经验
  3. 超细节!从源代码剖析Self-Attention知识点
  4. poj 1845 Sumdiv (算数基本定理+逆元)
  5. 阅读与html阅读的区别,w3c School读书笔记(一):HTML基础
  6. Mac OS使用技巧之八:Dock栏使用技巧
  7. [Vue.js]实战 -- 电商项目(七)
  8. 蔚来Q4经调整净亏损17亿元 部分车型将调价
  9. Google新项目:从一条线开始,完成地球的绘制
  10. 结构方程软件Lisrel 8.7 和HLM5.5
  11. github中文件夹名带数字,git下来为空文件夹
  12. 知识树 = 系统思维 + 外接大脑
  13. 要不要相信你的调研问卷
  14. 22 个最常用的 Python 包
  15. 总结 : 安卓开发大作业废话集合
  16. 多校9 HDU-6164 Dying Light 几何数学
  17. 安装驱动显卡重启计算机,win10系统电脑安装显卡驱动后一直重启的解决方案
  18. LienJack-2年前端面试心路历程(字节跳动、YY、虎牙、BIGO)
  19. MySQL Authentications
  20. adb命令行 查看手机 ip

热门文章

  1. Tensorflow object detection API应用大致流程
  2. pythonbyte转int_Python int与byte类型相互转化
  3. SWUST OJ#942 逆置顺序表
  4. Oracle 11g 安装之环境不满足最低要求
  5. IntelliJ IDEA注册激活
  6. 去掉Sublime text 3中的框框
  7. 栈的出栈次序及次序种类
  8. 非平凡空间 平凡空间
  9. 基于java+ssm+vue的中医养老服务平台设计
  10. win10本地安装部署ClickHouse