indexedDB存储

IndexedDB 是一种低级别的客户端存储技术,允许在浏览器中存储大量结构化数据,并支持索引查询。与传统的 Web 存储(如 LocalStorage 和 SessionStorage)相比,IndexedDB 的数据存储容量更大、查询更灵活,适用于存储大型数据集合。

IndexedDB 基于键值对存储数据,支持对象存储(类似数据库的表)。每个对象存储可以有多个索引(类似数据库的索引),用于加速查询。

1. 基本概念

  • 数据库(Database):包含数据的容器。
  • 对象存储(Object Store):类似数据库的“表”,存储实际的数据记录。
  • 事务(Transaction):在同一个数据库操作中,事务保证操作的一致性。
  • 索引(Index):通过某些字段(如产品名称)为对象存储创建索引,加速查询。
  • 游标(Cursor):允许按顺序遍历对象存储中的数据

2. IndexedDB 基本操作

2.1 打开数据库

打开(或创建)一个数据库,定义版本和对象存储结构。如果数据库版本发生变化,浏览器会触发 onupgradeneeded 事件来升级数据库。

// indexedDB.js
export const openDb = () => {
  const dbName = 'productDatabase'; // 数据库名称
  const version = 1; // 数据库版本(升级时会更新)
  
  return new Promise((resolve, reject) => {
    const request = indexedDB.open(dbName, version);
    
    request.onsuccess = (event) => {
      resolve(event.target.result);  // 返回数据库实例
    };
    
    request.onerror = (event) => {
      reject(event.target.error);  // 错误处理
    };
    
   // 数据库版本变化时会触发onupgradeneeded事件
    request.onupgradeneeded = (event) => {
      const db = event.target.result;
      // 创建存储对象,如果表格(objectStore)已经存在,则不再创建
      if (!db.objectStoreNames.contains('products')) {
        db.createObjectStore('products', { keyPath: 'id', autoIncrement: true });
      }
    };
  });
};
  • indexedDB.open() 方法用于打开数据库。
  • onsuccess 事件返回数据库实例。
  • onerror 事件处理打开数据库失败。
  • onupgradeneeded 事件触发数据库结构变化时,可以在这里创建对象存储(类似创建数据库表)。
  • transaction.objectStore('products') 获取一个对象存储(表)。
  • put() 方法用于插入或更新数据。
  • oncompleteonerror 事件处理事务成功或失败。
2.2 查询数据

使用 get()getAll() 方法获取数据。get() 根据主键获取单个数据,getAll() 获取所有数据。

// dbOperations.js
import { openDb } from './indexDB';

// 增加或更新一个产品
export const addProduct = async (product) => {
  const db = await openDb(); // 打开数据库
  const transaction = db.transaction('products', 'readwrite');   // 以读写模式开启事务
  const store = transaction.objectStore('products'); // 获取 'products' 对象存储
  store.put(product);  // put会根据主键是否存在决定是更新还是插入
  return new Promise((resolve, reject) => {
    transaction.oncomplete = () => resolve('Product added/updated successfully');
    transaction.onerror = (e) => reject(e.target.error);
  });
};

// 获取所有产品
export const getAllProducts = async () => {
  const db = await openDb(); // 打开数据库
  const transaction = db.transaction('products', 'readonly'); // 以只读模式开启事务
  const store = transaction.objectStore('products');
  const request = store.getAll();  // 获取所有产品

  return new Promise((resolve, reject) => {
    request.onsuccess = () => resolve(request.result);
    request.onerror = (e) => reject(e.target.error);
  });
};

// 删除一个产品
export const deleteProduct = async (id) => {
  const db = await openDb();
  const transaction = db.transaction('products', 'readwrite');
  const store = transaction.objectStore('products');
  store.delete(id);  // 删除指定ID的产品
  return new Promise((resolve, reject) => {
    transaction.oncomplete = () => resolve('Product deleted successfully');
    transaction.onerror = (e) => reject(e.target.error);
  });
};

// 更新产品
export const updateProduct = async (product) => {
  return addProduct(product);  // 更新功能和添加一样,直接调用addProduct
};

// 根据ID查询数据
const getProductById = async (id) => {
  const db = await openDb();  // 打开数据库
  const transaction = db.transaction('products', 'readonly');  // 只读事务
  const store = transaction.objectStore('products');  // 获取 products 对象存储

  const request = store.get(id);  // 使用 get 方法根据 ID 查询数据

  return new Promise((resolve, reject) => {
    request.onsuccess = () => {
      // 如果数据存在,返回数据,否则返回 null
      resolve(request.result || null); 
    };
    request.onerror = (e) => reject(e.target.error);  // 错误处理
  });
};

3. IndexedDB 使用场景

IndexedDB 适用于需要存储大量、结构化数据的场景,常见的使用案例包括:

  • 离线应用:当网络不可用时,可以利用 IndexedDB 存储用户数据和应用状态。
  • 本地缓存:用于在本地存储从服务器请求的数据,提高页面加载速度。
  • 大数据存储:例如,大量日志数据、图片、文件等,可以直接存储到浏览器中。

4. IndexedDB API 小结

  • open():打开数据库。
  • transaction():开启事务。
  • objectStore():访问对象存储(表)。
  • put():插入或更新数据。
  • get():获取指定主键的数据。
  • getAll():获取所有数据。
  • delete():删除数据。
  • onsuccess/onerror:处理成功和失败的回调。

5. 完整的 IndexedDB 封装示例

将上述操作封装成一个完整的模块,方便在 Vue.js 中调用:

<script>
import { getAllProducts, addProduct, deleteProduct, updateProduct } from './dbOperations';

export default {
  data() {
    return {
      products: [],
      filterQuery: '',
      showAddModal: false,
      editingProduct: null,
      newProduct: {
        name: '',
        price: '',
      },
    };
  },
  computed: {
    filteredProducts() {
      return this.products
        .filter((product) =>
          product.name.toLowerCase().includes(this.filterQuery.toLowerCase())
        )
        .sort((a, b) => {
          if (this.sortKey === 'name') {
            return a.name.localeCompare(b.name);
          } else if (this.sortKey === 'price') {
            return a.price - b.price;
          }
          return 0;
        });
    },
  },
  methods: {
    async loadProducts() {
      try {
        const products = await getAllProducts();
        console.log('Products loaded:', products);
        this.products = products;
      } catch (error) {
        console.error('Error loading products:', error);
      }
    },
    async saveProduct() {
      try {
        await addProduct(this.newProduct);
        this.loadProducts(); // 重新加载数据
        this.cancelEdit();
      } catch (error) {
        console.error('Error saving product:', error);
      }
    },
    async editProduct(product) {
      this.newProduct = { ...product };
      this.editingProduct = product;
      this.showAddModal = true;
    },
    async deleteProduct(id) {
      try {
        await deleteProduct(id);
        this.loadProducts(); // 重新加载数据
      } catch (error) {
        console.error('Error deleting product:', error);
      }
    },
    cancelEdit() {
      this.newProduct = { name: '', price: '' };
      this.editingProduct = null;
      this.showAddModal = false;
    },
  },
  mounted() {
    this.loadProducts(); // 页面加载时从IndexedDB获取数据
  },
};
</script>

通过这些操作,你可以非常方便地从 IndexedDB 中查询数据,并在 Vue.js 中展示和编辑数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

至_臻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值