前端数据库 indexedDB 简介

栏目: Html5 · 发布时间: 5年前

内容简介:作者 | Brilliant Open Web团队编辑 |

作者 | Brilliant Open Web团队

编辑 |  Brilliant Open Web团队

前面介绍到 Cache Storage 是基于键值对的方式缓存数据,是适用于存储和检索网络请求及响应的存储系统,不能提供搜索功能,不能建立自定义的索引。本文介绍的 indexedDB 是浏览器环境提供的本地数据库, 代了 WebSQL 作为 HTML5 的标准,允许存储大量的数据,提供查询接口,还能创建索引等等,适用于可离线的或者需要存储大量数据的 web app。

简介

indexedDB 是一个在浏览器环境中的非关系型数据库,具有以下特点:

  • 每个域名下可以新建多个数据库,数据库具有唯一的名字和可变的版本号

  • 每个数据库包含多个 objectStore (对象仓库),objectStore 类似于关系型数据库中的表,创建和修改 objectStore 需要升级数据库版本号

  • objectStore 用于保存 javascript object,通过 index (索引)查询和遍历数据

  • 基于 transaction (事务),所有数据操作都需要在事务中进行

  • api 基本是异步的,通过事件的回调处理

  • 遵循同源协议,只能访问同域中的数据库

indexedDB 的基本使用模式为:

  1. 打开数据库

  2. 创建/获取 objectStore

  3. 启动事务,操作数据库

  4. 监听相应事件,获得操作结果

  5. 处理操作结果

下面通过代码来介绍 indexedDB 的使用方法。

打开数据库

通过  indexedDB.open()  方法打开数据库,该方法接受两个参数,分别是数据库名和版本号,版本号默认是 1,改变版本的唯一方法是通过一个比当前版本号更高的值去打开数据库,这时会触发  upgradeneeded  事件。

和 indexedDB 其他异步方法相同,open() 需要我们在事件回调中执行相应的操作。


 

// 如果有 mydb 这个数据库,就直接打开

// 如果没有,就会创建 mydb 数据库

let request = window.indexedDB.open('mydb', 1)

request.onsuccess = e => {

// 获取数据库实例

let db = e.target.result

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

})

request.onerror = e => {

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

})

request.onupgradeneeded = e => {

let db = e.target.result

console.log("数据库版本升级")

// 修改数据库结构

}

创建 ObjectStore

objectStore 类似于关系型数据库中的表,存放着相关的所有数据。所谓的 “相关” 是指,这些 object 必须具备相同的一个属性名,也就是主键。所有 object 主键的值都是唯一的。

在 upgradeneeded 事件回调中使用  createObjectStore()  方法创建 objectStore,该方法接受两个参数:

  1. 仓库名,同一个数据库的仓库名不能重复

  2. 主键名 keyPath 以及主键是否自增 autoIncrement ,如果存入的某个 object 不存在主键,而 autoIncrement 为 false,那么就会报错,如果 autoIncrement 为 true,在没有主键的情况下,存入数据库的时候,会被自动添加上。


 

request.onupgradeneeded = e => {

let db = e.target.result

// 创建自增主键为 id 的对象仓库 mystore

db.createObjectStore('mystore', {keyPath: 'id', autoIncrement: true})

}

创建索引

在 indexedDB 中也存在索引,但和关系型数据库中索引的作用不同,indexedDB 的索引被指定为数据的某个属性,用于数据检索。所以看起来 objectStore 的索引,等效于关系型数据库中的表的字段。

创建索引实际上是对 objectStore 进行修改,因此,只能在数据库的 upgradeneeded 事件中处理,使用  createIndex()  方法创建索引,该方法接受三个参数:

  1. 索引名

  2. object 的属性名,可以是单个或一组属性名

  3. 可选参数,包括  unique  和  multiEntry ,unique 指定属性的值是否唯一,multiEntry 用于对属性值为数组的数据进行检索,如果为 true,则会检查数组中的每一个值,否则只检查整个数组。


 

request.onupgradeneeded = e => {

let db = e.target.result

// 注意这里应该进行判断是否已经存在这个 objectStore,在这里略过

let objectStore = db.createObjectStore(

'mystore',

{keyPath: 'id'}

)

// 创建 name 为索引

objectStore.createIndex('name', 'name', {unique: true})

}

启动事务

在对数据进行操作前,需要启动事务。通过  db.transaction()  方法可以启动事务,该方法接受两个参数:

  1. objectStore 名称,可以是单个或数组,指定事务可以操作的 objectStore

  2. 事务模式,可取值为  readonly  和  readwrite ,两者都可以从 objectStore 读取数据,但只有 readwrite 才能修改数据


 

request.onsuccess = e => {

let db = e.target.result

let transaction = db.transaction(

'myObjectStore',

'readonly'

)

}

增删改查

和任何数据库一样,indexedDB 也是进行数据存储,并提供一些方式让开发者可以对数据进行查询、添加、删除、修改。当一个事务开始之后,在它的生命周期以内,可以对 objectStore 进行数据操作,下面会通过一个简单的示例对 indexedDB 的增删改查操作进行介绍。

  • 添加数据 add() ,传入一个 object,主键值不能是已存在的,否则会添加失败

  • 更新数据 put() ,传入一个 object,如果主键值已存在,则更新仓库中的 object,如果没有,则添加这个 object。需要注意的是,如果主键是 autoIncrement 的,参数 object 中没有主键,那么 put() 会自动增加主键,将 object 添加到仓库中

  • 获取数据  get() ,传入一个主键值,可以获取对应的 object

  • 删除数据  delete() ,传入一个主键值,可以从 objectStore 中删除对应的 object


 

request.onsuccess = e => {

let db = e.target.result

let transaction = db.transaction(

['myObjectStore'],

'readwrite'

)

let objectStore = transaction.objectStore('myObjectStore')

// 获取主键值为 ‘100001’ 的数据

let getRequest = objectStore.get('100001')

getRequest.onsuccess = e => {

// 获取到的数据

let object = e.target.result

}

// 添加新数据

let addRequest = objectStore.add({

id: '100002',

name: 'Zhang Fei'

})

addRequest.onsuccess = e => {

console.log('写入成功!')

}

// 更新数据

let putRequest = objectStore.put({

id: '100002',

name: 'Zhang San'

})

putRequest.onsuccess = e => {

console.log('写入成功!')

}

// 删除数据

let delRequest = objectStore.delete('100001')

delRequest.onsuccess = e => {

console.log('删除成功')

}

}

检索

indexedDB 使用游标来检索数据。游标是一个机制,无法把游标打印出来看,但是可以通过游标得到你当前操作的元素,换句话说,游标有着类似 next() 的  continue()  方法,可以用来移动游标到下一个位置。

通过  openCursor()  方法打开游标,该方法接受两个可选参数:

  1. 范围,使用 IDBKeyRange 对象的四种方法定义范围:

  • 上边界  upperBound() ,如 IDBKeyRange.upperBound(10) 表示键值小于等于 10

  • 下边界  lowerBound() ,如 IDBKeyRange.lowerBound(10) 表示键值大于等于 10

  • 上下边界  bound() ,如 IDBKeyRange.bound(10, 20) 表示键值从 10 到 20

  • 单值  only() ,如 IDBKeyRange.only(10) 表示键值为 10

  • 方向,包括:

    • next ,升序遍历

    • nextunique ,升序遍历,对于重复数据只取第一条

    • prev ,降序遍历,

    • prevunique ,降序遍历,对于重复数据只取第一条

    在对应的  onsuccess  回调中, cursor  对象有以下属性和方法:

    • value ,游标当前所指的 object

    • continue() ,让游标滑动到下一个 object,并再次触发 onsuccess

    • update() ,更新数据

    • delete() ,删除数据

    
     

    request.onsuccess = e => {

    let db = e.target.result

    let transaction = db.transaction(

    ['myObjectStore'],

    'readonly'

    )

    let store = transaction.objectStore('myObjectStore')

    // 使用 price 索引(需要已创建 price 索引)

    let index = store.index('price')

    // 检索 price 值从 100 到 200 的数据

    let range = IDBKeyRange.bound(100, 200)

    let cursorRequest = index.openCursor(range)

    let results = []

    cursorRequest.onsuccess = e => {

    let cursor = e.target.result

    if (cursor) {

    results.push(cursor.value)

    cursor.continue()

    } else {

    // 遍历之后的 object 数据列表的结果

    console.log(results)

    }

    }

    }

    总结

    indexedDB 作为浏览器端的数据库,为 web app 提供了持久化存储数据的方法和丰富的查询能力,但是具有以下局限性:

    • 数据可能会被清除,比如退出隐私模式或者用户手动清除数据

    • 存储容量限制

    • 需要自行同步服务端数据

    另外由于其基于事务和使用异步 api 的特点,回调和错误处理会比较麻烦与复杂,使用起来不太方便,因此建议先对进行封装,参考: https://lavas-project.github.io/pwa-book/chapter03/5-indexeddb.html#%E5%88%A9%E7%94%A8-indexeddb-%E5%AE%9E%E7%8E%B0-db-%E7%B1%BB,也可以使用开源库:https://github.com/dfahlander/Dexie.js/ 和 https://github.com/erikolson186/zangodb

    本文内容主要来自开源书籍 《PWA 应用实战》 。该书由百度 Web 生态团队撰写与分享,记录了团队过去两年积累的 PWA 方面的经验,欢迎对 Web 和 PWA 有浓厚兴趣的读者加入我们,一起来维护这本书。

    前端数据库 indexedDB 简介

    Brilliant Open Web 

    BOW(Brilliant Open Web)团队,是一个专门的Web技术建设小组,致力于推动 Open Web 技术的发展,让Web重新成为开发者的首选。

    BOW 关注前端,关注Web;剖析技术、分享实践;谈谈学习,也聊聊管理。

    关注 OpenWeb开发者,让我们一起推动 OpenWeb技术的发展!

    前端数据库 indexedDB 简介

    OpenWeb开发者

    ID:BrilliantOpenWeb

    技术连接世界,开放赢得未来


    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

    查看所有标签

    猜你喜欢:

    本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

    淘宝、天猫电商运营百科全书

    淘宝、天猫电商运营百科全书

    刘涛 / 电子工业出版社 / 2016-7 / 59.00元

    有人说淘宝、天猫上90%的卖家不赚钱,我认为说得有点大了。因为如果说大家都不赚钱或者在亏钱,为什么去年在做店铺的卖家,今年还在继续?那些不赚钱的卖家,多数是没意识到市场的变化,还在用原来的套路运营店铺。市场在变,但卖家的思路却没有转变,不赚钱也在情理之中,因为淘宝、天猫的玩法变了。做店铺就是好比一场“打怪”升级的游戏,每次的升级都需要强大的装备与攻略。优胜劣汰,能活下去并且能赚钱的卖家,都是在不停......一起来看看 《淘宝、天猫电商运营百科全书》 这本书的介绍吧!

    SHA 加密
    SHA 加密

    SHA 加密工具

    RGB HSV 转换
    RGB HSV 转换

    RGB HSV 互转工具

    HSV CMYK 转换工具
    HSV CMYK 转换工具

    HSV CMYK互换工具