关于indexedDB的使用

一. indexedDB是什么

1.概念

IndexedDB 是一种在浏览器中用于存储大量结构化数据的 NoSQL 数据库

2.特点

存储量大
支持复杂数据结构,能够存储对象和二进制数据,并且可以使用索引来快速检索数据
异步操作
持久性存储

3. 使用场景

离线应用: 可以存储应用所需的数据,以便在离线状态下使用。例如,离线邮件客户端可以将邮件存储在 IndexedDB 中,以便用户在没有网络连接时也能查看邮件。

缓存数据:可以缓存服务器端的数据,以减少网络请求和提高应用的性能。例如,新闻应用可以将最近的新闻文章存储在 IndexedDB 中,以便用户在下次访问时能够更快地加载。

二. 一些概念

1. 基本的操作

IndexedDB 鼓励使用的基本模式如下所示:

打开数据库。
在数据库中创建一个对象存储(object store)。
启动事务,并发送一个请求来执行一些数据库操作,如添加或获取数据等。
通过监听正确类型的 DOM 事件以等待操作完成。
对结果进行一些操作(可以在 request 对象中找到)

2. 概念

(1)数据库 (database):IndexedDB 的数据库是相关数据的容器,每个域名可以创建多个数据库。数据库有版本控制,结构修改(如新增或删除表、索引)只能通过升级版本完成。
(2)对象存储 (object store):IndexedDB 使用对象存储而不是表,并且一个数据库可以包含任意数量的对象存储
(3)事务 (transaction):你需要开启一个事务才能对你创建的数据库进行操作。事务来自于数据库对象,而且你必须指定你想让这个事务跨越哪些对象存储。一旦你处于一个事务中,你就可以访问用于保存数据的对象存储
所有数据操作都在事务中进行,以确保数据的一致性和完整性。事务对象提供了error,abort,complete三个回调方法,监听操作结果。
事务提供了三种模式:readonly、readwrite 和 versionchange。
使用 readonly 或 readwrite 模式都可以从已存在的对象存储里读取记录。但只有在 readwrite 事务中才能修改对象存储。
必须在 versionchange 事务中才能修改数据库的“模式”或结构(包括新建或删除对象存储、索引)(此功能在web workers中可用)。
(4)索引(index):索引用于加速数据检索。每个对象存储可以为不同属性建立索引。
(5)游标(cursor):IDBCursor 对象, 游标用于遍历对象存储中的记录,支持从指定位置开始读取数据,并进行数据的批量操作。

总结: 一个indexedDB 可以有多个数据库,一个数据库有多个对象存储.
数据库开启的操作事务需要指定对象存储,然后进行访问。

三. 简单的封装使用

可以先看MDN给的例子,正常跑通基本逻辑,然后再根据自己的需求封装下。下面的indexedDB.js是工具类,vue文件是调用情况
目的:
给一个key和obj,实现数据的新增,能通过这个key查询,删除,修改
方案:
新增的时候,利用key作为对象存储的键路径, { [key]: key, value: obj}
查询的时候利用get()
删除的时候也通过这个key
修改的也是重置这个

// indexedDB.js
class IndexdedDB {
  constructor (name = 'custom', version = 1) {
    this.request = null
    this.db = null
    this.name = name
    this.version = version
  }
  // 因为获取数据库是异步操作,所以用promise封装下

  getDb (key) {
    return new Promise((resolve, reject) => {
      if (this.db) {
        resolve()
        return
      }

      // 打开数据库
      this.request = window.indexedDB.open(this.name, this.version)
      // 打开数据库的时候就应该创建对象存储
      this.request.onsuccess = (event) => { // 貌似用这个不行
        console.log('获取数据库成功')
        this.db = event.target.result
        resolve()
      }
      // 当你创建一个新的数据库或者增加已存在的数据库的版本号
      this.request.onupgradeneeded = (event) => {
        console.log('新建数据库成功')
        this.db = event.target.result
        this.objectStore = this.db.createObjectStore(key, { keyPath: key })
        this.objectStore.transaction.oncomplete = (event) => {
          console.log('对象存储已经存在')
        }
      }
      this.request.onerror = (event) => {
        // 针对此数据库请求的所有错误的通用错误处理器!
        console.error(`数据库错误:${event.target.errorCode}`)
        reject(new Error(`数据库错误:${event.target.errorCode}`))
      }
    })
  }

  // 新增数据, 用Key做为对象存储名字, 和keyPath
  async addData (key, data) {
    try {
      await this.getDb(key)
      const newData = {
        [key]: key,
        value: JSON.stringify(data)
      }
      // 先判断有没有在对象存储中,有的话就更新
      const res = await this.getData(key)
      if (res) {
        this.editData(key, newData)
        return
      }
      // 将数据保存到新创建的对象存储中。
      const customerObjectStore = this.db
        .transaction(key, 'readwrite')
        .objectStore(key)
      console.log('customerObjectStore', customerObjectStore)
      const addRequest = customerObjectStore.add(newData)
      addRequest.onsuccess = function () {
        console.log('Data added successfully:', newData)
      }
      addRequest.onerror = function (event) {
        console.log('Error adding data:', event.target.errorCode)
      }
    } catch (error) {

    }
  }
  // 获取数据

  async getData (key) {
    return new Promise(async (resolve, reject) => {
      await this.getDb()
      const transaction = this.db.transaction([key])
      const objectStore = transaction.objectStore(key)
      // 使用 get() 要求你知道你想要检索哪一个键
      const request = objectStore.get(key)
      request.onerror = (event) => {
        // 错误处理!
        reject(new Error('获取失败'))
      }
      request.onsuccess = (event) => {
        console.log('request.result', request.result)
        // 对 request.result 做些操作!
        request.result ? resolve(JSON.parse(request.result.value)) : resolve(null)
      }
    })
  }

  async editData (key, newData) {
    const objectStore = this.db
      .transaction([key], 'readwrite')
      .objectStore(key)
    const request = objectStore.get(key)
    request.onerror = (event) => {
    // 错误处理!
    }
    request.onsuccess = (event) => {
      console.log('objectStore', objectStore)
      // 把更新过的对象放回数据库。
      const requestUpdate = objectStore.put(newData)
      requestUpdate.onerror = (event) => {
      // 对错误进行处理
      }
      requestUpdate.onsuccess = (event) => {
      // 成功,数据已更新!
        console.log('成功,数据已更新!', event)
      }
    }
  }

  async delData (key) {
    await this.getDb()
    const request =
      this.db.transaction([key], 'readwrite')
        .objectStore(key)
        .delete(key)
    return new Promise((resolve, reject) => {
      request.onsuccess = (event) => {
        // 删除成功!
        console.log('删除成功')
        resolve()
      }
      request.onerror = function (event) {
        console.log('数据删除失败')
        reject(new Error('删除失败'))
      }
    })
  }
}

const indexedDB = new IndexdedDB()
export default indexedDB

<template>
  <div>
    <el-button type="primary" @click="operation.add">新增</el-button>
    <el-button type="primary" @click="operation.view">查看</el-button>
    <el-button type="primary" @click="operation.del">删除</el-button>
    <el-button type="primary" @click="operation.edit">编辑</el-button>
  </div>
</template>

<script>

import indexedDB from '@/utils/indexedDB'
export default {
  data () {
    return {
      operation: {
        add: this.add,
        view: this.view,
        edit: this.edit,
        del: this.del
      }
    }
  },
  methods: {
    add () {
      console.log('add')
      indexedDB.addData('a', {
        a: 'qiang'
      })
    },
    view () {
      console.log('view')
      indexedDB.getData('a').then(res => {
        console.log('res', res)
      })
    },
    edit () {
      console.log('edit')
      indexedDB.addData('a', { b: 'xiang' }).then(res => {
        console.log('res', res)
      })
    },
    del () {
      console.log('del')
      indexedDB.delData('a').then(res => {
        console.log('删除成功')
      })
    }
  }
}
</script>

<style>

</style>


posted @ 2024-11-07 17:33  这样就好了  阅读(47)  评论(0编辑  收藏  举报