介绍一下IndexedDB以及封装IndexedDB的模块代码

1. IndexedDB简介

IndexedDB 是一种在浏览器中存储结构化数据的方式,类似于关系数据库,但它具有更高的存储容量和灵活性。相比于 localStorageIndexedDB 适合存储大量数据,能够处理更复杂的数据结构,并且支持异步操作。它是浏览器端持久化存储的一种常用方式。

IndexedDB的特点:

  • 异步IndexedDB 操作大多数是异步的,因此不会阻塞 UI 线程。
  • 存储数据结构:能够存储 JavaScript 对象,包括数组、对象等结构化数据。
  • 大容量:浏览器的存储限制较高,通常比 localStorage 高得多(大多数浏览器在单个域名下允许存储 50MB 以上的数据)。
  • 事务支持:支持事务,使得对数据库的读写操作具有原子性。
  • 索引:可以为数据创建索引,提高检索效率。

IndexedDB的常见操作:

  • 打开数据库:通过 indexedDB.open() 打开(或者创建)数据库。
  • 创建对象存储(Object Store):相当于数据库表,用来存储实际的数据。
  • 事务(Transaction):所有的操作都在事务中进行,确保数据一致性。
  • 数据存取:支持 getputdelete 等操作。
  • 索引(Index):可以为数据创建索引,便于按字段查找数据。

2. 封装 IndexedDB 的模块代码

为了简化 IndexedDB 的使用,我们可以创建一些封装函数,以便于更容易地进行数据库操作。以下是一个简单的封装模块,提供了常见的 IndexedDB 操作,如打开数据库、保存数据、获取数据等。

indexedDB.js 模块:

// 打开或创建数据库
export const openDB = (dbName, storeName) => {
    return new Promise((resolve, reject) => {
        const request = indexedDB.open(dbName, 1); // 打开数据库,版本号设置为1

        // 数据库首次创建时或版本升级时会触发
        request.onupgradeneeded = (event) => {
            const db = event.target.result;
            // 如果数据库中没有这个对象存储,则创建它
            if (!db.objectStoreNames.contains(storeName)) {
                const store = db.createObjectStore(storeName, { keyPath: 'id' }); // 使用 'id' 作为主键
                store.createIndex('treeIndex', 'tree'); // 为 'tree' 字段创建索引
            }
        };

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

        // 打开失败
        request.onerror = (event) => {
            reject('数据库打开失败: ' + event.target.errorCode);
        };
    });
};

// 保存数据到数据库
export const saveToDB = (db, storeName, data) => {
    return new Promise((resolve, reject) => {
        const transaction = db.transaction(storeName, 'readwrite'); // 以读写模式打开事务
        const store = transaction.objectStore(storeName);
        const request = store.put(data); // 插入或更新数据

        request.onsuccess = () => {
            resolve('数据保存成功');
        };

        request.onerror = (event) => {
            reject('数据保存失败: ' + event.target.errorCode);
        };
    });
};

// 从数据库中获取数据
export const getFromDB = (db, storeName, id) => {
    return new Promise((resolve, reject) => {
        const transaction = db.transaction(storeName, 'readonly'); // 以只读模式打开事务
        const store = transaction.objectStore(storeName);
        const request = store.get(id); // 根据ID获取数据

        request.onsuccess = (event) => {
            resolve(event.target.result); // 返回获取到的结果
        };

        request.onerror = (event) => {
            reject('获取数据失败: ' + event.target.errorCode);
        };
    });
};

// 删除数据库中的数据
export const deleteFromDB = (db, storeName, id) => {
    return new Promise((resolve, reject) => {
        const transaction = db.transaction(storeName, 'readwrite');
        const store = transaction.objectStore(storeName);
        const request = store.delete(id); // 根据ID删除数据

        request.onsuccess = () => {
            resolve('数据删除成功');
        };

        request.onerror = (event) => {
            reject('数据删除失败: ' + event.target.errorCode);
        };
    });
};

3. 使用示例

初始化数据库:

const [db, setDb] = useState(null);

useEffect(() => {
    const initDB = async () => {
        const database = await openDB('CubeDataDB', 'treeStore');
        setDb(database);
    };
    initDB();
}, []);

获取数据:

const getSavedTreeState = async () => {
    if (db) {
        try {
            const savedState = await getFromDB(db, 'treeStore', queryUuid);
            return savedState ? savedState.tree : cubeStructTree;
        } catch (e) {
            console.error('Failed to get tree state from IndexedDB', e);
            return cubeStructTree;
        }
    }
    return cubeStructTree;
};

保存数据:

const saveTreeState = async (updatedTree) => {
    if (db) {
        try {
            await saveToDB(db, 'treeStore', { id: queryUuid, tree: updatedTree });
            console.log('Tree state saved to IndexedDB');
        } catch (e) {
            console.error('Failed to save tree state to IndexedDB', e);
        }
    }
};

删除数据:

const deleteSavedState = async () => {
    if (db) {
        try {
            await deleteFromDB(db, 'treeStore', queryUuid);
            console.log('Tree state deleted from IndexedDB');
        } catch (e) {
            console.error('Failed to delete tree state from IndexedDB', e);
        }
    }
};

4. 总结

  • IndexedDB 提供了一个浏览器端的数据库,能够处理大量数据并提供异步接口。
  • 我们封装了几个常用的 IndexedDB 操作,包括打开数据库、保存数据、获取数据和删除数据。
  • 在 React 中,通过 useEffect 打开数据库,并使用封装函数进行数据存取。

通过这种封装方式,你可以方便地在 React 项目中使用 IndexedDB 存储数据,避免了 localStorage 的存储限制,同时支持更复杂的数据结构。

posted on 2024-11-30 09:42  及途又八  阅读(352)  评论(0)    收藏  举报

导航