浏览器端使用indexedDB存储

你想知道如何在 IndexedDB 中根据 name(姓名)字段来查询数据,这是 IndexedDB 最常见的查询场景之一。要实现按姓名精准查找,核心是先为 name 字段创建索引,再通过索引进行查询。
一、完整实现代码(含建库、建索引、按姓名查询)
下面是一个开箱即用的完整示例,包含数据库初始化、创建索引、添加数据、按姓名查询的全部逻辑:

// 封装 IndexedDB 操作的工具函数
class IndexedDBHelper {
constructor(dbName, storeName, version = 1) {
this.dbName = dbName; // 数据库名
this.storeName = storeName; // 对象仓库名
this.version = version; // 数据库版本
this.db = null; // 数据库实例
}

// 1. 初始化数据库(创建仓库 + 为name字段建索引)
async initDB() {
return new Promise((resolve, reject) => {
// 打开数据库
const request = indexedDB.open(this.dbName, this.version);

// 数据库首次创建/版本升级时触发(用于初始化结构)
request.onupgradeneeded = (e) => {
this.db = e.target.result;
// 如果仓库不存在,创建仓库(主键设为id,自增)
if (!this.db.objectStoreNames.contains(this.storeName)) {
const store = this.db.createObjectStore(this.storeName, {
keyPath: 'id',
autoIncrement: true // id 自动递增
});
// 为 name 字段创建索引(name索引名,字段名,是否唯一:false表示允许多人同名)
store.createIndex('nameIndex', 'name', { unique: false });
console.log('仓库和name索引创建成功');
}
};

// 打开数据库成功
request.onsuccess = (e) => {
this.db = e.target.result;
resolve(this.db);
};

// 打开数据库失败
request.onerror = (e) => {
reject(new Error('打开数据库失败:' + e.target.error));
};
});
}

// 2. 新增数据(示例:添加用户)
async addUser(user) {
if (!this.db) await this.initDB();
return new Promise((resolve, reject) => {
// 开启读写事务
const transaction = this.db.transaction(this.storeName, 'readwrite');
const store = transaction.objectStore(this.storeName);
const request = store.add(user); // 添加数据

request.onsuccess = () => resolve('添加成功');
request.onerror = (e) => reject(new Error('添加失败:' + e.target.error));
});
}

// 3. 核心:按姓名(name)查询数据
async queryByName(name) {
if (!this.db) await this.initDB();
return new Promise((resolve, reject) => {
// 开启只读事务
const transaction = this.db.transaction(this.storeName, 'readonly');
const store = transaction.objectStore(this.storeName);
// 获取之前创建的name索引
const nameIndex = store.index('nameIndex');
// 按索引查询(精准匹配name)
const request = nameIndex.getAll(name); // getAll:返回所有匹配结果;get:返回第一个匹配结果

request.onsuccess = (e) => {
resolve(e.target.result); // 结果是数组(即使只有1条)
};

request.onerror = (e) => {
reject(new Error('查询失败:' + e.target.error));
};
});
}
}

// ------------------- 测试使用 -------------------
(async () => {
// 初始化:数据库名「userDB」,对象仓库名「userStore」
const dbHelper = new IndexedDBHelper('userDB', 'userStore');
await dbHelper.initDB();

// 先添加几条测试数据
await dbHelper.addUser({ name: '张三', age: 25, phone: '13800138000' });
await dbHelper.addUser({ name: '李四', age: 30, phone: '13900139000' });
await dbHelper.addUser({ name: '张三', age: 28, phone: '13700137000' }); // 同名数据

// 按姓名查询:查「张三」
const result = await dbHelper.queryByName('张三');
console.log('查询结果:', result);
// 输出:[{id:1, name:'张三', age:25, phone:'13800138000'}, {id:3, name:'张三', age:28, phone:'13700137000'}]
})();
View Code

二、关键逻辑解释
创建索引是前提:
在 onupgradeneeded 阶段(数据库初始化 / 升级),通过 store.createIndex('nameIndex', 'name', { unique: false }) 创建索引:
第一个参数 nameIndex:索引名称(自定义,后续查询要用到);
第二个参数 name:要索引的字段名(即你要查询的姓名字段);
第三个参数 unique: false:表示允许多条数据的 name 字段值相同(如果设为 true,则姓名不能重复)。

按索引查询的核心 API:
index.getAll(name):返回所有姓名匹配的结果(数组),适合处理 “同名” 场景;
index.get(name):返回第一个匹配的结果(单个对象),适合确认 “是否存在该姓名” 或 “姓名唯一” 的场景;
两者的区别:如果有多个 “张三”,get 只返回第一条,getAll 返回全部。

事务类型:
查询操作用 readonly(只读)事务,性能更高;
增删改操作必须用 readwrite(读写)事务。
三、扩展:模糊查询姓名(可选)
如果你需要 “模糊查询”(比如输入 “张”,查出所有姓张的人),可以用索引的范围查询:

// 新增模糊查询方法(加到 IndexedDBHelper 类中)
async queryByNameFuzzy(keyword) {
if (!this.db) await this.initDB();
return new Promise((resolve, reject) => {
const transaction = this.db.transaction(this.storeName, 'readonly');
const store = transaction.objectStore(this.storeName);
const nameIndex = store.index('nameIndex');
// 范围:以keyword开头(如keyword='张',匹配所有以张开头的姓名)
const range = IDBKeyRange.bound(keyword, keyword + '\uffff');
const request = nameIndex.getAll(range);

request.onsuccess = (e) => resolve(e.target.result);
request.onerror = (e) => reject(new Error('模糊查询失败:' + e.target.error));
});
}

// 调用:查询所有姓张的人
// const fuzzyResult = await dbHelper.queryByNameFuzzy('张');
// console.log('模糊查询结果:', fuzzyResult);
View Code

 

总结
按姓名查询 IndexedDB 的核心是先为 name 字段创建索引,再通过索引查询;
精准查询用 index.get(name)(单条)或 index.getAll(name)(多条),模糊查询用 IDBKeyRange 范围匹配;
操作 IndexedDB 必须通过事务,查询用只读事务,增删改用读写事务。

 

简单的代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>IndexedDB 增删改查示例</title>
</head>

<body>
    <button id="addBtn">添加数据</button>
    <button id="addBtns">添加数据</button>
    <button id="deleteBtn">删除数据</button>
    <button id="updateBtn">更新数据</button>
    <button id="queryBtn">查询数据</button>
    <button id="queryBtns">删除数据库</button>
    <script>
        // 打开或创建数据库
        const request = indexedDB.open('myDatabase', 1);

        // 数据库打开失败
        request.onerror = function (event) {
            console.error('数据库打开失败:', event.target.errorCode);
        };

        // 数据库打开成功
        request.onsuccess = function (event) {
            const db = event.target.result;
            console.log('数据库打开成功');

            // 添加数据
            document.getElementById('addBtn').addEventListener('click', function () {
                const transaction = db.transaction(['myObjectStore'], 'readwrite');
                const objectStore = transaction.objectStore('myObjectStore');
                const data = { id: 1, name: '李强', age: 30 };
                const addRequest = objectStore.add(data);
                addRequest.onsuccess = function () {
                    console.log('数据添加成功');
                };
                addRequest.onerror = function (event) {
                    console.error('数据添加失败:', event.target.errorCode);
                };
            });
            document.getElementById('addBtns').addEventListener('click', function () {
                const transaction = db.transaction(['myObjectStore'], 'readwrite');
                const objectStore = transaction.objectStore('myObjectStore');
                const data = { id: 64, name: '李是强', age: 30 };
                const addRequest = objectStore.add(data);
                addRequest.onsuccess = function () {
                    console.log('数据添加成功');
                };
                addRequest.onerror = function (event) {
                    console.error('数据添加失败:', event.target.errorCode);
                };
            });
                

            // 删除数据
            document.getElementById('deleteBtn').addEventListener('click', function () {
                const transaction = db.transaction(['myObjectStore'], 'readwrite');
                const objectStore = transaction.objectStore('myObjectStore');
                const deleteRequest = objectStore.delete(1);
                deleteRequest.onsuccess = function () {
                    console.log('数据删除成功');
                };
                deleteRequest.onerror = function (event) {
                    console.error('数据删除失败:', event.target.errorCode);
                };
            });

            // 更新数据
            document.getElementById('updateBtn').addEventListener('click', function () {
                const transaction = db.transaction(['myObjectStore'], 'readwrite');
                const objectStore = transaction.objectStore('myObjectStore');
                const data = { id: 1, name: 'Jane', age: 30 };
                const putRequest = objectStore.put(data);
                putRequest.onsuccess = function () {
                    console.log('数据更新成功');
                };
                putRequest.onerror = function (event) {
                    console.error('数据更新失败:', event.target.errorCode);
                };
            });

            // 查询数据
            document.getElementById('queryBtn').addEventListener('click', function () {
                const transaction = db.transaction(['myObjectStore'], 'readonly');
                const objectStore = transaction.objectStore('myObjectStore');
                
                // const getRequest = objectStore.get(1); //按照主键查找
                // const getRequest = objectStore.index('name').get('李强'); //按照主键查找
                // const getRequest = objectStore.index('name').getAll('李强'); //按照索引查找
                const getRequest = objectStore.getAll(); //查找全部

                getRequest.onsuccess = function (event) {
                    const result = event.target.result;
                    if (result) {
                        console.log('查询结果:', result);
                    } else {
                        console.log('未找到数据');
                    }
                };
                getRequest.onerror = function (event) {
                    console.error('数据查询失败:', event.target.errorCode);
                };
            });

        };

        // 数据库版本更新时创建对象仓库和索引
        request.onupgradeneeded = function (event) {
            const db = event.target.result;
            if (!db.objectStoreNames.contains('myObjectStore')) {
                const objectStore = db.createObjectStore('myObjectStore', { keyPath: 'id' });
                objectStore.createIndex('name', 'name', { unique: false });
                objectStore.createIndex('age', 'age', { unique: false });
            }
        };
    </script>
</body>

</html>
View Code

图片上传保存并获取展示

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>IndexedDB 图片存储(原生JS)</title>
    <style>
        .preview { border: 1px solid #ddd; min-height: 300px; margin: 20px 0; }
        button { padding: 8px 12px; margin-right: 10px; }
    </style>
</head>
<body>
    <input type="file" id="fileInput" accept="image/*">
    <button id="storeBtn">存储图片</button>
    <button id="loadBtn">加载最新图片</button>
    <div class="preview">
        <img id="dbImage" style="max-width: 100%; display: none;">
    </div>
    <div id="status">就绪</div>

    <script>
        // 核心配置
        const DB_NAME = "ImageDB";
        const STORE_NAME = "images";
        const DB_VERSION = 1;
        let db = null;

        // 状态更新
        function updateStatus(message) {
            document.getElementById('status').textContent = message;
        }

        // 1. 初始化数据库(Promise封装)
        function initDB() {
            return new Promise((resolve, reject) => {
                const request = indexedDB.open(DB_NAME, DB_VERSION);

                // 数据库结构升级
                request.onupgradeneeded = (event) => {
                    const db = event.target.result;
                    // 关键修复:确保对象存储存在
                    if (!db.objectStoreNames.contains(STORE_NAME)) {
                        db.createObjectStore(STORE_NAME, { 
                            keyPath: 'id', 
                            autoIncrement: true 
                        });
                        updateStatus("对象存储创建成功");
                    }
                };

                request.onsuccess = (event) => {
                    db = event.target.result;
                    updateStatus("数据库已连接");
                    resolve(db);
                };

                request.onerror = (event) => {
                    updateStatus(`数据库错误: ${event.target.error}`);
                    reject(event.target.error);
                };
            });
        }

        // 2. 存储图片到数据库
        async function storeImage() {
            const file = document.getElementById('fileInput').files[0];
            if (!file) {
                updateStatus("请选择图片文件");
                return;
            }

            try {
                // 读取为ArrayBuffer(兼容性更好)
                const arrayBuffer = await new Promise((resolve, reject) => {
                    const reader = new FileReader();
                    reader.onload = () => resolve(reader.result);
                    reader.onerror = () => reject(reader.error);
                    reader.readAsArrayBuffer(file);
                });

                const transaction = db.transaction([STORE_NAME], 'readwrite');
                const store = transaction.objectStore(STORE_NAME);

                // 构建元数据对象
                const imageData = {
                    name: file.name,
                    type: file.type,
                    size: file.size,
                    timestamp: new Date(),
                    imageData: arrayBuffer
                };

                // 存储操作
                const request = store.add(imageData);
                
                request.onsuccess = () => {
                    updateStatus(`图片存储成功 ID: ${request.result}`);
                };
                
                request.onerror = (event) => {
                    updateStatus(`存储失败: ${event.target.error}`);
                };
                
            } catch (error) {
                updateStatus(`错误: ${error.message}`);
            }
        }

        // 3. 从数据库加载最新图片
        async function loadLatestImage() {
            const transaction = db.transaction([STORE_NAME], 'readonly');
            const store = transaction.objectStore(STORE_NAME);
            const request = store.openCursor(null, 'prev'); // 反向遍历取最新
            
            request.onsuccess = (event) => {
                const cursor = event.target.result;
                if (cursor) {
                    displayImage(cursor.value);
                } else {
                    updateStatus("数据库中没有图片");
                }
            };
            
            request.onerror = (event) => {
                updateStatus(`加载失败: ${event.target.error}`);
            };
        }

        // 4. 显示图片
        function displayImage(imageRecord) {
            const blob = new Blob([imageRecord.imageData], { type: imageRecord.type });
            const imageUrl = URL.createObjectURL(blob);
            
            const imgElement = document.getElementById('dbImage');
            imgElement.src = imageUrl;
            imgElement.style.display = 'block';
            imgElement.alt = `已加载: ${imageRecord.name}`;
            
            // 释放内存
            imgElement.onload = () => URL.revokeObjectURL(imageUrl);
            
            updateStatus(`已加载: ${imageRecord.name} (${formatBytes(imageRecord.size)})`);
        }

        // 辅助函数:格式化文件大小
        function formatBytes(bytes) {
            const units = ['B', 'KB', 'MB', 'GB'];
            let size = bytes;
            let unitIndex = 0;
            
            while (size >= 1024 && unitIndex < units.length - 1) {
                size /= 1024;
                unitIndex++;
            }
            return `${size.toFixed(2)} ${units[unitIndex]}`;
        }

        // 5. 初始化应用
        window.addEventListener('DOMContentLoaded', async () => {
            updateStatus("正在初始化数据库...");
            try {
                await initDB();
                
                // 绑定事件
                document.getElementById('storeBtn').addEventListener('click', storeImage);
                document.getElementById('loadBtn').addEventListener('click', loadLatestImage);
                
                updateStatus("就绪:选择图片后点击存储");
            } catch (error) {
                updateStatus(`初始化失败: ${error.message}`);
            }
        });
    </script>
</body>
</html>

uniapp中VUE3封装使用

在utils创建一个groupChatDb.js

/**
 * IndexedDB 封装工具类(适配 UniApp H5 + Vue3)
 * 仅支持 H5 环境,其他端提示不支持
 */
class UniIndexedDB {
    constructor(dbName = 'myDatabase', storeName = 'myObjectStore', version = 1) {
        this.dbName = dbName;
        this.storeName = storeName;
        this.version = version;
        this.db = null;
        this.isSupport = this.checkSupport();
    }

    // 检查环境是否支持 IndexedDB
    checkSupport() {
        // #ifdef H5
        return !!window.indexedDB;
        // #endif
        // #ifndef H5
        uni.showToast({
            title: '当前环境不支持IndexedDB',
            icon: 'none'
        });
        return false;
        // #endif
    }

    // 打开/创建数据库
    openDB() {
        return new Promise((resolve, reject) => {
            if (!this.isSupport) {
                reject(new Error('当前环境不支持IndexedDB'));
                return;
            }
            const request = window.indexedDB.open(this.dbName, this.version);
            // 版本更新/首次创建时初始化仓库
            request.onupgradeneeded = (event) => {
                this.db = event.target.result;
                if (!this.db.objectStoreNames.contains(this.storeName)) {
                    // ========== 1开启autoIncrement,指定主键fid自增 ==========
                    const objectStore = this.db.createObjectStore(this.storeName, {
                        keyPath: 'fid', // 主键字段仍为fid
                        autoIncrement: true // 核心:开启原生自增
                    });
                    objectStore.createIndex('id', 'id', {unique: false});
                    objectStore.createIndex('conversationsId', 'conversationsId', {unique: false});
                    // 新增:为fid创建索引(方便排序查询,虽然主键本身可直接排序,但显式索引更清晰)
                    objectStore.createIndex('fid', 'fid', {unique: true});
                }
            };
            // 打开成功
            request.onsuccess = (event) => {
                this.db = event.target.result;
                resolve('数据库打开成功');
            };
            // 打开失败
            request.onerror = (event) => {
                reject(new Error(`数据库打开失败: ${event.target.error}`));
            };
        });
    }

    // 关闭数据库
    closeDB() {
        if (this.db) {
            this.db.close();
            this.db = null;
        }
    }
    // 删除整个数据库(核心功能)
    deleteDB() {
        return new Promise((resolve, reject) => {
            if (!this.isSupport) {
                reject(new Error('当前环境不支持IndexedDB'));
                return;
            }
            // 先关闭已打开的连接
            this.closeDB();
            const request = window.indexedDB.deleteDatabase(this.dbName);
            request.onsuccess = () => {
                resolve('数据库删除成功');
            };
            request.onerror = (event) => {
                reject(new Error(`数据库删除失败: ${event.target.error}`));
            };
            // 有未关闭的连接时触发
            request.onblocked = () => {
                reject(new Error('数据库删除被阻止:存在未关闭的连接'));
            };
        });
    }

    // 通用事务处理(封装重复逻辑)
    _transaction(mode, callback) {
        return new Promise((resolve, reject) => {
            if (!this.db) {
                reject(new Error('数据库未打开,请先调用openDB'))
                return;
            }
            try {
                const transaction = this.db.transaction(this.storeName, mode);
                const objectStore = transaction.objectStore(this.storeName);
                resolve(callback(objectStore));
            } catch (error) {
                reject(error);
            }
        });
    }
    
    // 根据主键fID查询数据
    queryDataByFid(fid) {
        return this._transaction('readonly', (objectStore) => {
            return new Promise((resolve, reject) => {
                const request = objectStore.get(fid);
                request.onsuccess = (event) => resolve(event.target.result);
                request.onerror = (event) => reject(new Error(`查询失败: ${event.target.error}`));
            });
        });
    }
    // 根据 id 查询 这个id是 聊天信息id
    queryDataById(id) {
        return this._transaction('readonly', (objectStore) => {
            return new Promise((resolve, reject) => {
                const request = objectStore.index('id').get(id); //按照主键查找
                request.onsuccess = (event) => resolve(event.target.result);
                request.onerror = (event) => reject(new Error(`查询失败: ${event.target.error}`));
            });
        });
    }
    //根据群组唯一id查询所有群组数据 - 分页
    queryDataAllId(conversationsId, pageNum = 1, pageSize = 10) {
        const self = this
        return this._transaction('readonly', (objectStore) => {
            return new Promise((resolve, reject) => {
                try {
                    const index = objectStore.index('conversationsId');
                    const range = IDBKeyRange.only(conversationsId);
                    const countRequest = index.count(range);
    
                    countRequest.onsuccess = () => {
                        const total = countRequest.result;
                        const totalPage = Math.ceil(total / pageSize);
                        let resultList = [];
                        const start = (pageNum - 1) * pageSize;
                        const end = pageNum * pageSize;
    
                        // 提前判断页码越界
                        if (pageNum > totalPage) {
                            resolve({
                                list: [],
                                total: total,
                                pageNum: pageNum,
                                pageSize: pageSize,
                                totalPage: totalPage,
                                hasMore: false
                            });
                            return;
                        }
    
                        let currentIndex = 0;
                        const cursorRequest = index.openCursor(range, 'prev');
    
                        cursorRequest.onsuccess = (event) => {
                            const cursor = event.target.result;
                            if (cursor) {
                                if (currentIndex >= start && currentIndex < end) {
                                    resultList.push(cursor.value);
                                }
                                currentIndex++;
                                if (currentIndex >= end) {
                                    cursor.continue = () => {};
                                    resolveResult();
                                    return;
                                }
                                cursor.continue();
                            } else {
                                resolveResult();
                            }
                        };
    
                        cursorRequest.onerror = (event) => {
                            reject(new Error(`分页查询失败: ${event.target.error}`));
                        };                  
                        function resolveResult() {
                            resolve({
                                list: self.transformContentJson(resultList),
                                total: total,
                                pageNum: pageNum,
                                pageSize: pageSize,
                                totalPage: totalPage,
                                hasMore: pageNum < totalPage
                            });
                        }
                    };
    
                    countRequest.onerror = (event) => {
                        reject(new Error(`统计总条数失败: ${event.target.error}`));
                    };
                } catch (error) {
                    reject(new Error(`分页查询异常: ${error.message}`));
                }
            });
        });
    }
    
    //根据群组唯一id查询所有群组数据 不分页
    noPageDataAllId(conversationsId) {
        return this._transaction('readonly', (objectStore) => {
            return new Promise((resolve, reject) => {
                const request = objectStore.index('conversationsId').getAll(conversationsId); //按照群组id查找
                request.onsuccess = (event) => resolve(this.transformContentJson(event.target.result));
                request.onerror = (event) => reject(new Error(`查询失败: ${event.target.error}`));
            });
        });
    }
    
    //获取所有的数据 
    queryDataAll(conversationsId) {
        return this._transaction('readonly', (objectStore) => {
            return new Promise((resolve, reject) => {
                const request = objectStore.getAll();
                request.onsuccess = (event) => resolve(event.target.result);
                request.onerror = (event) => reject(new Error(`查询失败: ${event.target.error}`));
            });
        });
    }

    // 添加数据(无需传fid,自动生成)
    addData(data) {
        return this._transaction('readwrite', (objectStore) => {
            return new Promise((resolve, reject) => {
                const request = objectStore.add(data);
                // 成功时返回自动生成的fid(event.target.result就是自增的fid)
                request.onsuccess = (event) => resolve({
                    msg: '数据添加成功',
                    fid: event.target.result // 返回自动生成的主键ID
                });
                request.onerror = (event) => reject(new Error(`添加失败: ${event.target.error}`));
            });
        });
    }

    // 删除单条数据(根据fid删除)不传直接清空
    deleteData(id = null) {
        return this._transaction('readwrite', (objectStore) => {
            return new Promise((resolve, reject) => {
                let request
                if(id){
                    request = objectStore.delete(id);
                }else{
                    request = objectStore.clear();
                }
                request.onsuccess = () => resolve('数据删除成功');
                request.onerror = (event) => reject(new Error(`删除失败: ${event.target.error}`));
            });
        });
    }
    
    // 新增:批量删除指定conversationsId的所有数据
    deleteDataByConversationsId(conversationsId) {
        return this._transaction('readwrite', (objectStore) => {
            return new Promise((resolve, reject) => {
                try {
                    // 1. 获取conversationsId索引
                    const index = objectStore.index('conversationsId');
                    // 2. 创建匹配指定conversationsId的范围
                    const range = IDBKeyRange.only(conversationsId);
                    // 3. 打开游标遍历所有匹配的数据
                    const request = index.openCursor(range);
                    let deleteCount = 0; // 统计删除的条数

                    request.onsuccess = (event) => {
                        const cursor = event.target.result;
                        if (cursor) {
                            // 4. 删除当前游标指向的数据(通过主键fid删除)
                            cursor.delete();
                            deleteCount++;
                            // 5. 继续遍历下一条
                            cursor.continue();
                        } else {
                            // 6. 游标遍历完成,返回删除结果
                            if (deleteCount === 0) {
                                resolve(`未找到conversationsId为${conversationsId}的数据,无需删除`);
                            } else {
                                resolve(`成功删除${deleteCount}条conversationsId为${conversationsId}的数据`);
                            }
                        }
                    };
                    request.onerror = (event) => {
                        reject(new Error(`批量删除失败: ${event.target.error}`));
                    };
                } catch (error) {
                    reject(new Error(`批量删除异常: ${error.message}`));
                }
            });
        });
    }
    
    // 更新数据(需传入包含fid的完整数据)
    updateData(data) {
        return this._transaction('readwrite', (objectStore) => {
            return new Promise((resolve, reject) => {
                const request = objectStore.put(this.purifyData(data));
                request.onsuccess = () => resolve('数据更新成功');
                request.onerror = (event) => reject(new Error(`更新失败: ${event.target.error}`));
            });
        });
    }

    transformContentJson(arr) {
        // 边界校验:非数组返回空数组或原数据
        if (!Array.isArray(arr)) {
            console.warn('传入的参数不是数组');
            return arr || [];
        }
        // 需要转换为布尔值的字段列表
        const booleanFields = ['joinGroups', 'leaveGroups', 'atmosphere', 'mute', 'revoke', 'revokeEdit', 'chat', 'violation', 'longPress'];
        return arr.map(item => {
            // 浅拷贝原对象,避免修改原始数据
            const newItem = { ...item };
            // 第一步:处理contentJson字段(字符串 → 对象/null)
            const contentJsonStr = newItem.contentJson;
            try {
                if (contentJsonStr === "NULL" || contentJsonStr === null) {
                    newItem.contentJson = null;
                } else if (typeof contentJsonStr === 'string' && contentJsonStr.trim() !== '') {
                    newItem.contentJson = JSON.parse(contentJsonStr);
                }else {
                    newItem.contentJson = contentJsonStr;
                }
            } catch (error) {
                console.error(`解析contentJson失败:${contentJsonStr},错误:`, error);
            }
    
            // 第二步:处理指定字段转为布尔值(0→false,1→true,NULL/其他→false)
            booleanFields.forEach(field => {
                const fieldValue = newItem[field];
                // 处理"NULL"字符串、null、undefined → 转为false
                if (fieldValue === "NULL" || fieldValue === null || fieldValue === undefined) {
                    newItem[field] = false
                }else if (fieldValue === 0 || fieldValue === "0") {// 数字/字符串 0 → false;数字/字符串 1 → true
                    newItem[field] = false
                }else if (fieldValue === 1 || fieldValue === "1") {
                    newItem[field] = true
                }else {// 其他异常值(如2、"2")→ 默认为false(可根据需求调整)
                    newItem[field] = false
                }
            })
            return newItem
        })
    }
    
    purifyData(data) { //序列化一次用于修改数据报错
      if (data === null || typeof data !== 'object') {
        return data; // 基础类型直接返回
      }
      // 核心:通过JSON序列化+反序列化,过滤所有不支持的内容
      try {
        return JSON.parse(JSON.stringify(data));
      } catch (error) {
        console.error('数据净化失败,降级为浅拷贝:', error);
        // 降级方案:手动浅拷贝(避免循环引用导致JSON序列化失败)
        const pureObj = Array.isArray(data) ? [] : {};
        for (const key in data) {
          // 只处理自身属性,跳过原型链属性
          if (Object.prototype.hasOwnProperty.call(data, key)) {
            const value = data[key];
            // 只保留基础类型、数组、纯对象
            if (['string', 'number', 'boolean', 'null', 'undefined'].includes(typeof value)) {
              pureObj[key] = value;
            } else if (Array.isArray(value)) {
              pureObj[key] = this.purifyData(value);
            } else if (typeof value === 'object' && value !== null) {
              pureObj[key] = this.purifyData(value);
            }
          }
        }
        return pureObj;
      }
    }
    
}

// 导出实例(全局单例)
export default new UniIndexedDB();

 在使用地方调用

import indexedDB from '@/utils/groupChatDb' //链接创建
 const res = await indexedDB.openDB()//打开并创键数据库
//使用
const resd = await indexedDB.deleteDataByConversationsId(res.data.group.id)

 

参考文章

[](https://blog.csdn.net/deku_ln/article/details/105431593)
[](https://cloud.tencent.com/developer/article/2541274)

 

posted @ 2026-03-24 14:44  瞎BB的是2B  阅读(41)  评论(0)    收藏  举报