React Native Realm中Division多类型组件的Schema设计方案咨询
最优Schema设计方案:抽象基类+多态组件列表
核心思路
利用Realm支持的对象继承特性,定义一个抽象基类DivisionElement作为所有组件(LineChart、DataTable等)的父类,让Division直接持有一个List<DivisionElement>类型的属性,存储各种组件对象,从根源解决之前三种方案的缺陷。
Schema 代码实现
// 抽象基类:所有Division组件的父类 const DivisionElementSchema = { name: 'DivisionElement', primaryKey: 'id', properties: { id: 'string', type: 'string', // 标识具体组件类型,方便渲染和查询区分 sortOrder: 'int', // 控制组件在Division中的显示顺序 // 所有组件共用的通用属性 isVisible: { type: 'bool', default: true }, title: 'string?' }, abstract: true // 标记为抽象类,禁止直接实例化 }; // 具体组件:折线图 const LineChartSchema = { name: 'LineChart', inheritFrom: 'DivisionElement', properties: { // 折线图专属属性 dataSource: 'string', lineColor: 'string', showLegend: { type: 'bool', default: true } } }; // 具体组件:数据表 const DataTableSchema = { name: 'DataTable', inheritFrom: 'DivisionElement', properties: { // 数据表专属属性 columnCount: 'int', rowHeight: 'float', enableSorting: { type: 'bool', default: false } } }; // Division 模型 const DivisionSchema = { name: 'Division', primaryKey: 'id', properties: { id: 'string', name: 'string', // 直接持有多态组件列表 elements: { type: 'list', objectType: 'DivisionElement' } } }; // 初始化Realm时注册所有Schema const realm = await Realm.open({ schema: [DivisionElementSchema, LineChartSchema, DataTableSchema, DivisionSchema] });
方案优势
- 增删改高效:直接操作Division的
elements列表,无需额外关联表,读写性能与普通列表一致,解决方案1的慢操作问题。 - 无空引用冗余:每个组件仅存储自身专属属性,基类存储公共属性,不存在方案2的大量空引用浪费。
- 查询效率高:Division直接持有组件列表,查询时可直接加载所有关联组件,无需反向遍历,解决方案3的查询低效问题。
- 扩展性强:新增组件只需添加对应子类Schema,无需修改现有结构,符合开闭原则。
操作示例
// 创建Division并添加不同类型组件 realm.write(() => { const division = realm.create('Division', { id: 'div_001', name: '销售数据分区' }); // 添加折线图 division.elements.push(realm.create('LineChart', { id: 'chart_001', type: 'LineChart', sortOrder: 0, title: '月度销量趋势', dataSource: 'sales_monthly', lineColor: '#2196F3' })); // 添加数据表 division.elements.push(realm.create('DataTable', { id: 'table_001', type: 'DataTable', sortOrder: 1, title: '销售明细', columnCount: 4, rowHeight: 44 })); }); // 查询Division及其所有组件 const division = realm.objects('Division').filtered('id = "div_001"')[0]; // 遍历组件时通过type区分类型 division.elements.forEach(element => { switch(element.type) { case 'LineChart': console.log('折线图数据源:', element.dataSource); break; case 'DataTable': console.log('数据表列数:', element.columnCount); break; } });
备选方案:嵌入式对象+类型标识(无继承)
如果不想依赖Realm的继承特性,可采用嵌入式对象结合类型标识的方式,将所有组件属性统一放在一个模型中,通过type字段区分类型:
const DivisionElementSchema = { name: 'DivisionElement', embedded: true, // 标记为嵌入式对象,直接存储在Division的elements列表中 properties: { type: 'string', sortOrder: 'int', isVisible: { type: 'bool', default: true }, title: 'string?', // 折线图专属属性 dataSource: 'string?', lineColor: 'string?', showLegend: 'bool?', // 数据表专属属性 columnCount: 'int?', rowHeight: 'float?', enableSorting: 'bool?' } }; const DivisionSchema = { name: 'Division', primaryKey: 'id', properties: { id: 'string', name: 'string', elements: { type: 'list', objectType: 'DivisionElement' } } };
这种方案实现简单,但存在少量可选属性冗余,适合组件类型较少、属性差异不大的场景。
内容的提问来源于stack exchange,提问作者Georgy
相关产品推荐
相关产品推荐

