Flutter Web中Dart操作IndexedDB的索引及对象存读问题
问题解答
问题1:是否需要使用dart:js包将Dart对象转换为JavaScript对象?
不需要。核心原因是IndexedDB的结构化克隆算法不支持直接存储自定义Dart类实例——它只能处理原生JS类型(比如对象、数组、基本类型、Blob等)。用dart:js手动转换不仅繁琐,还会破坏跨平台兼容性(如果项目后续要支持移动端/桌面端),绝非最优解。
问题2:是否需要将对象序列化为JSON字符串存储,这种情况下索引是否仍能生效?
推荐将Dart对象序列化为Map<String, dynamic>(而非纯JSON字符串)存储,此时索引完全可以正常生效:
- 若存JSON字符串,IndexedDB无法解析字符串内部的字段,自然没法基于字段创建索引;
- 若存
Map<String, dynamic>,idb_shim会自动将其转换为原生JS对象,你可以在onUpgradeNeeded中针对Map的特定字段创建索引,查询时也能通过索引快速筛选。
修改后的代码示例
存入逻辑(假设你的Dart对象有toJson()方法可转为Map)
IdbFactory idbFactory = getIdbFactory(); _db = await idbFactory.open(boxName, version: 1, onUpgradeNeeded: this.onUpgradeNeeded); var txn = _db.transaction(boxName, idbModeReadWrite); var store = txn.objectStore(boxName); // 将Dart对象转为Map后存储 await store.put(value.toJson(), key); await txn.completed;
读取逻辑(假设你的Dart对象有fromJson()构造方法)
var txn = _db.transaction(boxName, idbModeReadOnly); var store = txn.objectStore(boxName); // 读取得到Map后转为Dart对象 final Map<String, dynamic> jsonMap = await store.getObject(key) as Map<String, dynamic>; await txn.completed; return T.fromJson(jsonMap);
创建索引示例(在onUpgradeNeeded方法中)
void onUpgradeNeeded(VersionChangeEvent event) { var db = event.database; // 创建对象仓库 var store = db.createObjectStore(boxName); // 针对Map中的"username"字段创建索引 store.createIndex('username_idx', 'username', unique: false); }
补充说明
如果你的Dart对象没有toJson()/fromJson()方法,可以用json_serializable包自动生成序列化代码,这是Flutter生态中处理对象序列化的标准方案,比手动编写更可靠。
内容的提问来源于stack exchange,提问作者Vishnu
相关产品推荐
相关产品推荐

