Vue 中封装 IndexedDB 本地图片存储(支持 Blob)

📦 Vue 中封装 IndexedDB 本地图片存储(支持 Blob)

🎯 功能目标:将图片 Blob 存入浏览器 IndexedDB,并在组件中便捷使用。


🧱 一、封装模块:indexedDbImage.ts

📁 路径:src/utils/indexedDbImage.ts

// utils/indexedDbImage.ts
import { openDB, type IDBPDatabase } from 'idb'

const DB_NAME = 'ImageCacheDB'
const STORE_NAME = 'images'

interface ImageRecord {
  id: string // 图片唯一 ID,例如:uuid 或 hash
  blob: Blob
  createdAt: number
}

let db: IDBPDatabase | null = null

// 初始化图片库
export async function initImageDB() {
  db = await openDB(DB_NAME, 1, {
    upgrade(database) {
      if (!database.objectStoreNames.contains(STORE_NAME)) {
        const store = database.createObjectStore(STORE_NAME, {
          keyPath: 'id',
        })
        store.createIndex('createdAt', 'createdAt')
      }
    },
  })
}

// 添加图片(Blob)
export async function saveImage(id: string, blob: Blob) {
  if (!db) throw new Error('DB 未初始化')
  const tx = db.transaction(STORE_NAME, 'readwrite')
  const store = tx.objectStore(STORE_NAME)
  await store.put({ id, blob, createdAt: Date.now() })
  await tx.done
}

// 获取图片 URL
export async function getImageURL(id: string): Promise<string | null> {
  if (!db) throw new Error('DB 未初始化')
  const tx = db.transaction(STORE_NAME, 'readonly')
  const record = await tx.objectStore(STORE_NAME).get(id)
  return record ? URL.createObjectURL(record.blob) : null
}

// 删除图片
export async function deleteImage(id: string) {
  if (!db) throw new Error('DB 未初始化')
  await db.transaction(STORE_NAME, 'readwrite').objectStore(STORE_NAME).delete(id)
}

// 获取所有图片 ID(可用于展示缩略图列表)
export async function getAllImageIds(): Promise<string[]> {
  if (!db) throw new Error('DB 未初始化')
  return await db.getAllKeys(STORE_NAME) as string[]
}

🚀 二、初始化:main.ts

import { createApp } from 'vue'
import App from './App.vue'
import { initImageDB } from './utils/indexedDbImage'

await initImageDB()

createApp(App).mount('#app')

🖼 三、组件中使用图片存储功能

📄 ImageUploader.vue

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { saveImage, getImageURL, getAllImageIds } from '@/utils/indexedDbImage'

const previewUrls = ref<string[]>([])

const handleUpload = async (event: Event) => {
  const input = event.target as HTMLInputElement
  const file = input.files?.[0]
  if (file) {
    const id = crypto.randomUUID() // 或 file.name
    await saveImage(id, file)
    await loadImages()
  }
}

const loadImages = async () => {
  const ids = await getAllImageIds()
  const urls = await Promise.all(ids.map(id => getImageURL(id)))
  previewUrls.value = urls.filter(Boolean) as string[]
}

onMounted(() => {
  loadImages()
})
</script>

<template>
  <div class="img-upload">
    <h3>🖼 本地图片存储</h3>
    <input type="file" accept="image/*" @change="handleUpload" />
    <div class="img-preview">
      <img v-for="url in previewUrls" :key="url" :src="url" alt="图片" />
    </div>
  </div>
</template>

<style scoped>
.img-preview {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}
.img-preview img {
  width: 120px;
  border-radius: 8px;
}
</style>

✅ 支持功能总结

功能方法
初始化图片数据库initImageDB()
保存图片 BlobsaveImage(id, blob)
获取图片 Blob URLgetImageURL(id)
获取所有图片 IDgetAllImageIds()
删除图片deleteImage(id)

🔍 补充建议

  • 若需支持过期自动清理,可在 createdAt 字段加定期清除逻辑。
  • 可搭配 FileReader 实现缩略图生成。
  • 若用于聊天缓存,可按消息 messageId 保存图片,支持富文本插图。

📌 总结

本地存储图片在以下场景极其有用:

  • ✅ 离线应用(PWA)
  • ✅ 聊天记录本地缓存图片
  • ✅ 表单草稿本地图片暂存
  • ✅ 提高首屏加载体验(缓存头像、缩略图)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值