什么是 indexedDB

IndexedDB 是一种使用浏览器存储大量数据的方法.它创造的数据可以被查询,并且可以离线使用. IndexedDB对于那些需要存储大量数据,或者是需要离线使用的程序是非常有效的解决方法. --- MDN

  上面是MDN上对于IndexedDB的介绍.其简单而言,indexedDB就是一个基于事务操作的key-value型数前端数据库.其API大多是异步的

创建一个indexedDB数据库

const request = indexedDB.open('myDatabase', 1);

request.addEventListener('success', e => {

console.log('连接数据库成功');

});

request.addEventListener('error', e => {

console.log('连接数据库失败');

});

  在上面代码中我们使用indexedDB.open()创建一个indexedDB数据库.open()方法接受可以接受两个参数.第一个是数据库名,第二个是数据库的版本号.同时返回一个IDBOpenDBRequest对象用于操作数据库.其中对于open()的第一个参数数据库名,open()会先去查找本地是否已有这个数据库,如果有则直接将这个数据库返回,如果没有,则先创建这个数据库,再返回.对于第二个参数版本号,则是一个可选参数,如果不传,默认为1.但如果传入就必须是一个整数.

  在通过对indexedDB.open()方法拿到一个数据库对象IDBOpenDBRequest我们可以通过监听这个对象的success事件和error事件来执行相应的操作.

创建一个对象仓库

  再有了一个数据库之后,我们获取就想要去存储数据了,但是单只有数据库还不够,我们还需要有对象仓库(object store).对象仓库(object store)是indexedDB数据库的基础,其类似于MySQL中表的概念.

要创建一个对象仓库必须在upgradeneeded事件中,而upgradeneeded事件只会在版本号更新的时候触发.这是因为indexedDB API中不允许数据库中的数据仓库在同一版本中发生变化

const request = indexedDB.open('myDatabase', 2);

request.addEventListener('upgradeneeded', e => {

const db = e.target.result;

const store = db.createObjectStore('Users', {

keyPath: 'userId',

autoIncrement: false

});

console.log('创建对象仓库成功');

});

  在上述代码中我们监听upgradeneeded事件,并在这个事件触发时使用createObjectStore()方法创建了一个对象仓库.createObjectStore()方法接受两个参数,第一个是对象仓库的名字,在同一数据库中,仓库名不能重复.第二个是可选参数.用于指定数据的主键,以及是否自增主键.

创建事务

  OK现在我们有了数据库和对象仓库了,我们是否就可以存储数据了了.很抱歉,还是不行.我们还差最后一样东西----事务.

什么是事务

一个数据库事务通常包含了一个序列的对数据库的读/写操作。它的存在包含有以下两个目的

  上面是维基百科上对数据库事务的解释.简单来说事务就是用来保证数据库操作要么全部成功,要么全部失败的一个限制.比如,在修改多条数据时,前面几条已经成功了.,在中间的某一条是失败了.那么在这时,如果是基于事务的数据库操作,那么这时数据库就应该重置前面数据的修改,放弃后面的数据修改.直接返回错误,一条数据也不修改.

const request = indexedDB.open('myDatabase', 3);

request.addEventListener('success', e => {

const db = e.target.result;

const tx = db.transaction('Users', 'readwrite');

});

上述代码中我们使用transaction()来创建一个事务.transaction()接受两个参数,第一个是你要操作的对象仓库名称,第二个是你创建的事务模式.传入 readonly时只能对对象仓库进行读操作,无法写操作.可以传入readwrite进行读写操作.

操作数据

  好了现在有了数据库,对象仓库,事务之后我们终于可以存储数据了.

  • add() : 增加数据。接收一个参数,为需要保存到对象仓库中的对象。

  • put() : 增加或修改数据。接收一个参数,为需要保存到对象仓库中的对象。

  • get() : 获取数据。接收一个参数,为需要获取数据的主键值。

  • delete() : 删除数据。接收一个参数,为需要获取数据的主键值。

add 和 put 的作用类似,区别在于 put 保存数据时,如果该数据的主键在数据库中已经有相同主键的时候,则会修改数据库中对应主键的对象,而使用 add 保存数据,如果该主键已经存在,则保存失败。

添加数据

const request = indexedDB.open('myDatabase', 3);

request.addEventListener('success', e => {

const db = e.target.result;

const tx = db.transaction('Users', 'readwrite');

const store = tx.objectStore('Users');

const reqAdd = store.add({

'userId': 1,

'userName': '李白',

'age': 24

});

reqAdd.addEventListener('success', e => {

console.log('保存成功')

})

});

获取数据

const request = indexedDB.open('myDatabase', 3);

request.addEventListener('success', e => {

const db = e.target.result;

const tx = db.transaction('Users', 'readwrite');

const store = tx.objectStore('Users');

const reqGet = store.get(1);

reqGet.addEventListener('success', e => {

console.log(this.result.userName);

})

});

删除数据

const request = indexedDB.open('myDatabase', 3);

request.addEventListener('success', e => {

const db = e.target.result;

const tx = db.transaction('Users', 'readwrite');

const store = tx.objectStore('Users');

const reqDelete = store.delete(1);

reqDelete.addEventListener('success', e => {

console.log('删除数据成功');

})

});

使用游标

  在上面当中我们使用get()方法传入一个主键来获取数据,但是这样只能够获取到一条数据.如果我们想要获取多条数据了怎么办.我们可以使用游标,来获取一个区间内的数据.

  要使用游标,我们需要使用对象仓库上的openCursor()方法创建币打开.openCursor()方法接受两个参数.

openCursor(range?: IDBKeyRange | number | string | Date | IDBArrayKey, direction?: IDBCursorDirection): IDBRequest;

  第一个是范围,范围可以是一个IDBKeyRange对象.用以下方式创建.

var boundRange = IDBKeyRange.bound(1, 10, false, false);

var onlyRange = IDBKeyRange.only(1);

var lowerRange = IDBKeyRange.lowerBound(1, false);

var upperRange = IDBKeyRange.upperBound(10, false);

  第二个参数是方向.主要有一下几种

next : 游标中的数据按主键值升序排列,主键值相等的数据都被读取

nextunique : 游标中的数据按主键值升序排列,主键值相等只读取第一条数据

prev : 游标中的数据按主键值降序排列,主键值相等的数据都被读取

prevunique : 游标中的数据按主键值降序排列,主键值相等只读取第一条数据

  下面让我们来看一个完整的例子

const request = indexedDB.open('myDatabase', 4);

request.addEventListener('success', e => {

const db = e.target.result;

const tx = db.transaction('Users', 'readwrite');

const store = tx.objectStore('Users');

const range = IDBKeyRange.bound(1, 10);

const req = store.openCursor(range, 'next');

req.addEventListener('success', e => {

const cursor = this.result;

if (cursor) {

console.log(cursor.value.userName);

cursor.continue();

} else {

console.log('检索结束');

}

})

});

  在上面的代码中如果检索到符合条件的数据时,我们可以:

使用cursor.value拿到数据.

使用cursor.updata()更新数据.

使用cursor.delete()删除数据.

使用cursor.continue()读取下一条数据.

索引

  在上面代码中我们获取数据都是用的主键.但是,在很多情况下我们并不知道我们需要数据的主键是什么,我们知道一个大概的条件.比如说年龄大于20岁的用户.这个时候我们就需要用到索引.以便有条件的查找.

创建索引

  我们使用对象仓库的createIndex()方法来创建一个索引.

createIndex(name: string, keyPath: string | string[], optionalParameters?: IDBIndexParameters): IDBIndex;

createIndex()方法接收三个参数:

  1. 第一个参数name是索引名,不能重复.

  2. 第二个参数keyPath是你要在存储对象上的那个属性上建立索引,可以是一个单个的key值,也可以是一个包含key值集合的数组.

  3. 第三个参数optionalParameters是一个可选的对象参数{unique, multiEntry}

    • unique: 用来指定索引值是否可以重复,为true代表不能相同,为false时代表可以相同

    • multiEntry: 当第二个参数keyPath为一个数组时.如果multiEntry是true,则会以数组中的每个元素建立一条索引.如果是false,则以整个数组为keyPath值,添加一条索引.

  下面让我们来看一个完整的例子,我们建立一条用户年龄的索引.

const request = indexedDB.open('myDatabase', 5);

request.addEventListener('upgradeneeded', e => {

const db = e.target.result;

const store = db.createObjectStore('Users', {

keyPath: 'userId',

autoIncrement: false

});

const idx = store.createIndex('ageIndex', 'age', {

unique: false

})

});

  这样我们就创建了一条索引.

创建索引

  这在创建了一条索引之后我们就可以来使用它了.我们使用对象仓库上的index方法,通过传入一个索引名.来拿到一个索引对象.

const index = store.index('ageIndex');`

  然后我们就可以使用这个索引了.比如说我们要拿到年龄在20岁以上的数据,升序排列.

const request = indexedDB.open('myDatabase', 4);

request.addEventListener('success', e => {

const db = e.target.result;

const tx = db.transaction('Users', 'readwrite');

const store = tx.objectStore('Users');

const index = store.index('ageIndex');

const req = index.openCursor(IDBKeyRange.lowerBound(20), 'next');

req.addEventListener('success', e => {

const cursor = e.target.result;

if (cursor) {

console.log(cursor.value.age);

cursor.continue();

} else {

console.log('检索结束');

}

})

});

indexedDB 的兼容性

上面是我对indexedDB一些粗浅的总结,希望对大家有所帮助.如果文中有何不当之处请予以斧正,谢谢.

indexedDB介绍的更多相关文章

  1. 浏览器数据库IndexedDB介绍

    摘要 在移动端H5页面开发的时候,为了更好的提高用户体验,可以对不常变化的数据做浏览器端数据缓存,在用户打开页面的时候,首先加载本地的数据,然后异步请求服务端,更新数据.在移动端webview中,可以 ...

  2. web API简介(四):客户端储存之IndexedDB API

    概述 前篇:web API简介(三):客户端储存之Web Storage API 客户端储存从某一方面来说和动态网站差不多.动态网站是用服务端来储存数据,而客户端储存是用客户端来储存数据. Index ...

  3. 使用IndexedDB缓存给WebGL三维程序加速

    前言 使用webgl开发三维应用的时候,经常会发现三维场景加载比较慢,往往需要等待挺长时间,这样用户的体验就很不友好. 造成加载慢的原因,主要是三维应用涉及到的资源文件会特别多,这些资源文件主要是模型 ...

  4. HTML5的三种存储方式以及区别

    首先将存储方式前要先知道为什么要使用他:一是利用本地数据,介绍网络请求:二是弱网环境下,高延迟,低带宽,要把数据本地化: 1.本地存储localStorage和sessionStorage 介绍: 存 ...

  5. HTML5本地存储——IndexedDB(一:基本使用)

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

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

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

  7. [转]使用 HTML5 IndexedDB API

    本地数据持久性提高了 Web 应用程序可访问性和移动应用程序响应能力 索引数据库 (IndexedDB) API(作为 HTML5 的一部分)对创建具有丰富本地存储数据的数据密集型的离线 HTML5 ...

  8. HTML5 indexedDB数据库的入门学习(一)

    笔者早些时间看过web sql database,但是不再维护和支持,所以最近初步学习了一下indexedDB数据库,首先indexedDB(简称IDB)和web sql database有很大的差别 ...

  9. 前端的数据库:IndexedDB 。 ps:入门

    应用程序需要数据.对大多数Web应用程序来说,数据在服务器端组织和管理,客户端通过网络请求获取.随着浏览器变得越来越有能力,因此可选择在浏览器存储和操纵应用程序数据. 本文向你介绍名为IndexedD ...

随机推荐

  1. Unity "Build failed : Asset is marked as don't save " 解决方案

    编译到Android时失败,是字体的原因: -- -- 摘自官方论坛排第二但点赞第一的回答. http://answers.unity3d.com/questions/363963/build-fai ...

  2. Pyhton学习——Day22

    #有缩进的代码表示局部作用域的代码#if_name_ =='_main_' # while True#先引入一个os模块import os,sys,time,json# print(os.path.d ...

  3. 算法21----重塑矩阵 LeetCode566

    1.题目 在MATLAB中,有一个非常有用的函数 reshape,它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据. 给出一个由二维数组表示的矩阵,以及两个正整数r和c,分别表示想要的重 ...

  4. Use gdb attach pid and debug it

  5. [TJOI2015]线性规划

    题目:洛谷P3973.BZOJ3996. 题目大意:给你n,参数b[][]和c[](里面的数均>0),要你求一个数组A[](0/1,1表示选择),已知:1. 若同时选择X和Y,获得B[x][y] ...

  6. 马上着手开发 iOS 应用程序

    https://developer.apple.com/library/ios/referencelibrary/GettingStarted/RoadMapiOSCh/chapters/Introd ...

  7. [luogu]P4365[九省联考]秘密袭击coat(非官方正解)

    题目背景 警告:滥用本题评测者将被封号 We could have had it all. . . . . . 我们本该,拥有一切 Counting on a tree. . . . . . 何至于此 ...

  8. 在Vue中使用了Swiper ,动态从后台获取数据的之后,swiper滑动失效??

    在Vue中使用了Swiper ,动态从后台获取数据的之后,swiper滑动失效?? 是因为swiper提前初始化了,那时候数据还没有完全出来.这里有两种解决办法 1. 使用vue提供的$nextTic ...

  9. HashMap导致死循环问题

    虽然我推测是链表形成闭环,但 没有去证明过.从网上找了一下: http://blog.csdn.net/autoinspired/archive/2008/07/16/2662290.aspx 里面也 ...

  10. maven打包可运行的jar包(包含依赖工程)

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...