# 认识 IndexedDB

  • 什么是 IndexedDB 呢?
    • 我们能看到 DB 这个词,就说明它其实是一种数据库(Database),通常情况下在服务器端比较常见;
    • 在实际的开发中,大量的数据都是存储在数据库的,客户端主要是请求这些数据并且展示;
    • 有时候我们可能会存储一些简单的数据到本地(浏览器中),比如 token、用户名、密码、用户信息等,比较少存储大量的数据;
    • 那么如果确实有大量的数据需要存储,这个时候可以选择使用 IndexedDB;
  • IndexedDB 是一种底层的 API,用于在客户端存储大量的结构化数据。
    • 它是一种事务型数据库系统,是一种基于 JavaScript 面向对象数据库,有点类似于 NoSQL(非关系型数据库);
    • IndexDB 本身就是基于事务的,我们只需要指定数据库模式,打开与数据库的连接,然后检索和更新一系列事务即可;

# IndexedDB 的连接数据库

  • 第一步:打开 indexDB 的某一个数据库;

    • 通过 indexDB.open (数据库名称,数据库版本) 方法;
    • 如果数据库不存在,那么会创建这个数据;
    • 如果数据库已经存在,那么会打开这个数据库;
  • 第二步:通过监听回调得到数据库连接结果;

    • 数据库的 open 方法会得到一个 IDBOpenDBRequest 类型
  • 我们可以通过下面的三个回调来确定结果:

    • onerror:当数据库连接失败时;
    // 打开数据 (和数据库建立连接)
     const dbRequest = indexedDB.open("nekoaimer")
     dbRequest.onerror = function(err) {
       console.log("比如浏览器不支持,打开数据库失败~")
     }
    • onsuccess:当数据库连接成功时回调;
    // 数据库连接成功时回调;
    let db = null
    dbRequest.onsuccess = function(event) {
      db = event.target.result
      console.log(db)  
    }
    • onupgradeneeded:当数据库的 version 发生变化并且高于之前版本时回调;
    • 我们可以通过 onsuccess 回调的 event 获取到 db 对象:event.target.result
    // 第一次打开 / 或者版本发生升级
    dbRequest.onupgradeneeded = function(event) {
      const db = event.target.result
      console.log(db) // IDBDatabase {name: 'nekoaimer', version: 1, objectStoreNames: DOMStringList, onabort: null, onclose: null, …}
      // 创建一些存储对象
      db.createObjectStore("users", { keyPath: "id" })
    }
    • 通常我们在这里会创建具体的存储对象:db.createObjectStore (存储对象名称,{ keypath: 存储的主键})

# IndexedDB 的数据库操作

  • 我们对数据库的操作要通过事务对象来完成:
    • 第一步:通过 db 获取对应存储的事务 db.transaction (存储名称,可写操作);
    • 第二步:通过事务获取对应的存储对象 transaction.objectStore (存储名称);
  • 接下来我们就可以进行增删改查操作了:
    • 新增数据 store.add
    • 查询数据
      • 方式一:store.get (key)
      • 方式二:通过 store.openCursor 拿到游标对象
        • 在 request.onsuccess 中获取 cursor:event.target.result
        • 获取对应的 key:cursor.key;
        • 获取对应的 value:cursor.value;
        • 可以通过 cu rsor.continue 来继续执行;
    • 修改数据 cursor.update (value)
    • 删除数据 cursor.delete ()

# IndexedDB 数据库的使用

  • HTML
<button>新增</button>
<button>查询</button>
<button>修改</button>
<button>删除</button>
  • 数据
class User {
  constructor(id, name, age) {
    this.id = id
    this.name = name
    this.age = age
  }
}
const users = [
  new User(001, "lain", 16),
  new User(002, "saber", 17),
  new User(003, "aimer", 18)
]
  • 整体结构
// 获取四个按钮
const btns = document.querySelectorAll("button")
for (let i = 0; i < btns.length; i++) {
  btns[i].onclick = function () {
    // 操作哪一张表
    const transaction = db.transaction("users", "readwrite")
    // 从 transaction 事务里拿 users 对象,因为 transaction 是可以传多个的 ["users"]
    const store = transaction.objectStore("users")
    console.log(store)
    switch (i) {
      case 0:
        console.log("点击了新增")
        break
      case 1:
        console.log("点击了查询")
        break
      case 2:
        console.log("点击了删除")
        break
      case 3:
        console.log("点击了修改")
        break
    }
  }

# 新增数据

case 0:
  console.log("点击了新增")
  for (const user of users) {
    //add 新增数据 并且每一次返回一个对象
    const request = store.add(user)
    // 每条数据插入成功的回调
    request.onsuccess = function() {
      console.log(`${user.name}插入成功`)
    }
  }
  // 事务全部完成后回调 oncomplete 函数
  transaction.oncomplete = function() {
    console.log("添加操作全部完成")
  }
  break
// 点击后插入成功打印下面信息
/* 
   点击了新增
   lain 插入成功
   saber 插入成功
   aimer 插入成功
   添加操作全部完成
*/

# 查询数据

  • 查询方式一 (知道主键,根据主键查询)
  • 如果没查询到返回 undefined
case 1:
  console.log("点击了查询")
  const request = store.get(001)
  request.onsuccess = function(event) {
    console.log(event.target.result) 
  }
  break
// 点击查询后打印下面信息
/* 
  点击了查询
  {id: 1, name: 'lain', age: 16}
*/
  • 查询方式二
case 1:
  const request = store.openCursor()
  request.onsuccess = function (event) {
    const cursor = event.target.result
    if (cursor) {
      // 如果找到 key 就不用查了
      if (cursor.key === 002) {
        console.log(cursor.key, cursor.value)
      } else {
        // 没找到继续查
        cursor.continue()
      }
    } else {
      // 如果查询完都没找到打印 查询完成
      console.log("查询完成")
    }
  }
  break
// 点击查询后打印下面信息
/* 
  点击了查询
  2 {id: 2, name: 'saber', age: 17}
*/

# 修改数据

  • 获取游标并修改 name ,最好记得一定要用游标将 value 放进去
  • 这些操作可在 IndexedDB 里验证查看
  • , 注意每次数据发生变化或有一句提示 Data may be stale , 记得 Refresh ,再查看 IndexedDB 数据库
case 2:
  console.log("点击了修改")
  const updateRequest = store.openCursor()
  updateRequest.onsuccess = function(event) {
    const cursor = event.target.result
    if (cursor) {
      if (cursor.key === 003) {
        const value = cursor.value;
        value.name = "樱岛麻衣"
        // 再用游标将 value 放进去 可以在 IndexedDB 里验证查看
        cursor.update(value)
        
        // 打印看看
        console.log(cursor.key, cursor.value)
      } else {
        cursor.continue()
      }
    } else {
      console.log("查询完成")
    }
  }
  break
// 点击 x 修改后打印下面信息
/* 
  点击了修改
  3 {id: 3, name: ' 樱岛麻衣 ', age: 18}
*/

# 删除数据

  • 删除数据后,最好去 IndexedDB 查看数据是否删除
case 3:
  console.log("点击了删除")
  const deleteRequest = store.openCursor()
  deleteRequest.onsuccess = function(event) {
    const cursor = event.target.result
    if (cursor) {
      if (cursor.key === 002) {
        // 找到对应游标的 delete
        cursor.delete()
      } else {
        cursor.continue()
      }
    } else {
      console.log("查询完成")
    }
  }
break
// 点击删除后打印下面信息,最好去 IndexedDB 数据库查看
/* 
  点击了删除
*/
Update on Views times

Give me a cup of [coffee]~( ̄▽ ̄)~*

Nico Niconi WeChat Pay

WeChat Pay

Nico Niconi Alipay

Alipay