什么是 IndexedDB
IndexedDB 用于在用户的浏览器中存储大量结构化数据。它允许你创建、读取、更新和删除对象存储(Object Store)中的数据,并支持事务,以确保数据操作的原子性和一致性。IndexedDB 适合存储大量数据,并且可以在离线状态下使用。
IndexedDB 的原理
IndexedDB 基于事务和对象存储的原理,支持以下操作:
- 数据库:IndexedDB 数据库包含一个或多个对象存储。每个数据库有一个名称和版本号。版本号用于管理数据库的升级。
- 对象存储:类似于表的概念,每个对象存储包含若干键值对。键值对中的键必须是唯一的。
- 事务:所有对 IndexedDB 的读写操作都是在事务中执行的。事务确保操作的原子性和一致性。
- 索引:可以在对象存储上创建索引,以便快速查询数据。
IndexedDB 的使用场景
IndexedDB 适用于以下场景:
- 离线存储:应用需要在离线状态下存储和访问数据。
- 大量数据存储:需要存储和管理大量结构化数据。
- 复杂查询:需要对数据进行复杂查询和筛选操作。
- 本地缓存:用于缓存服务器数据,提高应用性能。
在 React 中使用 IndexedDB
在 React 中使用 IndexedDB,可以借助一些库来简化操作,比如 idb
或 dexie
。以下是使用 idb
库的示例:
1. 安装 idb
库
首先,安装 idb
库:
npm install idb
2. 创建 IndexedDB 实例
创建一个文件 db.js
,用于初始化数据库和定义数据操作:
// src/db.js
import { openDB } from 'idb';
const DB_NAME = 'my-database';
const DB_VERSION = 1;
const STORE_NAME = 'my-store';
export const initDB = async () => {
return openDB(DB_NAME, DB_VERSION, {
upgrade(db) {
if (!db.objectStoreNames.contains(STORE_NAME)) {
db.createObjectStore(STORE_NAME, { keyPath: 'id', autoIncrement: true });
}
},
});
};
export const addItem = async (db, item) => {
const tx = db.transaction(STORE_NAME, 'readwrite');
const store = tx.objectStore(STORE_NAME);
await store.add(item);
await tx.done;
};
export const getItems = async (db) => {
const tx = db.transaction(STORE_NAME, 'readonly');
const store = tx.objectStore(STORE_NAME);
return store.getAll();
};
3. 在 React 组件中使用 IndexedDB
在 React 组件中,使用 useEffect
钩子初始化数据库,并定义操作函数:
// src/App.js
import React, { useState, useEffect } from 'react';
import { initDB, addItem, getItems } from './db';
function App() {
const [db, setDb] = useState(null);
const [items, setItems] = useState([]);
const [inputValue, setInputValue] = useState('');
useEffect(() => {
const init = async () => {
const database = await initDB();
setDb(database);
const allItems = await getItems(database);
setItems(allItems);
};
init();
}, []);
const handleAddItem = async () => {
if (db && inputValue) {
await addItem(db, { value: inputValue });
const allItems = await getItems(db);
setItems(allItems);
setInputValue('');
}
};
return (
<div>
<h1>IndexedDB Example</h1>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<button onClick={handleAddItem}>Add Item</button>
<ul>
{items.map((item) => (
<li key={item.id}>{item.value}</li>
))}
</ul>
</div>
);
}
export default App;