indexedDB 使用

2,893 阅读4分钟

前言

讲到前端存储,可能会想到 cookie、localStorage、sessionStorage、web SQL database(已经凉了)、indexedDB,本文主要讨论的就是indexedDB

IndexedDB 就是浏览器提供的本地数据库,它可以被网页脚本创建和操作。IndexedDB 允许储存大量数据,提供查找接口,还能建立索引。这些都是 LocalStorage 所不具备的。

通过使用 indexedDB 来写了一个demo,可以通过访问 我的codepen 查看源码

对比

对比 cookie localStorage sessionStorage indexedDB
存储大小 4kb 5M 5M 不少于 250MB,甚至没有上限
与服务器端通信 每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题 仅在客户端(即浏览器)中保存,不参与和服务器的通信
生命周期 一般由服务器生成,可设置失效时间。如果在浏览器端生成Cookie,默认是关闭浏览器后失效 除非被清除,否则永久保存 仅在当前会话下有效,关闭页面或浏览器后被清除 除非被清除,否则永久保存
使用场景 判断用户是否登录 存储一些内容稳定的资源。比如图片内容丰富的电商网站会用它来存储 Base64 格式的图片字符串 存储一些当前会话的信息,比如微博的 sessionStorage就主要是存储你本次会话的浏览足迹 和 localStorage 用途类似:
1.  存储量会更大
2. localStorage使用简单字符串键值对在本地存储数据,而indexedDB可以存储任意类型的值(适合键值对较多的数据,如果使用 localStorage 存储每次都要写入,写出需要字符串化和对象化)

indexedDB 和 localStorage 兼容性对比

查看工具
👇localStorage

👇indexedDB

如果你想指定自己的浏览器是什么内核,什么版本的可以通过浏览器版本检测器查看

使用步骤

打开数据库

var request = window.indexedDB.open(databaseName, version);

第一个参数是字符串,表示数据库的名字。如果指定的数据库不存在,就会新建数据库。第二个参数是整数,表示数据库的版本。如果省略,打开已有数据库时,默认为当前版本;新建数据库时,默认为1。

indexedDB.open()方法返回一个 IDBRequest 对象,这个对象通过三种事件error、success、upgradeneeded,处理打开数据库的操作结果。

success 事件表示成功打开数据库,通过 request.result 拿到数据库对象的结果

upgradeneeded 事件 如果指定的版本号,大于数据库的实际版本号,就会发生数据库升级事件upgradeneeded,首次新建数据库也会触发这个事件

打开数据库重点 :

  1. 拿到数据库对象的结果,如果已经存在

新建数据库

新建对象仓库(即新建表),指定表名,指定id作为主键

request.onupgradeneeded = function(event) {
  db = event.target.result;
  var objectStore = db.createObjectStore('person', { keyPath: 'id' ,autoIncrement:true});
}

db.objectStoreNames.contains('person') 可以判断表是否已经存在,如果不存在去创建一张新表

新建索引:objectStore.createIndex('address','address') 索引名称,索引所在的属性

创建数据库的重点:

  1. 新建对象仓库,相当于表的概念
  2. 通过对象仓库来新建索引

增数据 objectStore.add

新建一个事务。新建时必须指定表格名称和操作模式(“只读”或“读写”)。事务的概念非常重要,增删改查的功能都是基于事务来执行的

let transaction = db.transaction('project','readwrite')
let objectStore = transaction.objectStore('project')
let request = objectStore.add(params)
request.onsuccess = function(event){
    let result = event.target.result
}

通过事务 transaction.objectStore('project')方法拿到指定对象仓库(表对象),再通过表对象的 add 方法向表格写入一条数据。

重点:

  1. 新建一个事务的概念,任何增删改查的操作之前都需要新建事务
  2. 拿到对象仓库(表对象),然后通过表对象的 add 方法添加数据。
  3. 写入数据是异步的过程,表对象操作后会返回一个request对象,可以request对象上的 success,error 事件来监听操作是否成功

删 objectStore.delete

都要 新建事务,所以可以将公共的逻辑抽离出来

const getObjectStore = (db,databaseName)=> {
  return new Promise(resolve=>{
    const objectStore = db.transaction([databaseName], "readwrite").objectStore(databaseName)
    resolve(objectStore)
  })
}
    // 通过id删除对应数据
    let objectStore = getObjectStore(db,'project');
    const objectStoreRequest = objectStore.delete(id);
    // 删除成功后
    objectStoreRequest.onsuccess = function() {
        resolve('已删除')
    };

查 objectStore.get

let objectStore = getObejectStore(db,'project')
let request = objectStore.get(id)
request.onsuccess = function(event){
    // 获取到当前数据
    const record = request.result
}

改 objectStore.put

let objectStore = getObejectStore(db,'project')
let request = objectStore.get(id)
request.onsuccess = function(event){
    // 获取到当前数据
    const record = request.result
    // 更新数据库中存储数据
    // 需要保持原来数据的指针,所以不采用直接赋值的方式
    objectStore.put(Object.assign(record,{newKey1:value1})
}

结尾

上面只介绍了最基础的增删改查的功能,其实 indexedDB是一个比较复杂的 API,涉及不少概念。想了解更多内容,可以查看我下面推荐链接,也可以看我的 codepen源码实例

参考IndexedDB API