如何在ngrx/data中设置非数组类型的单一实体?
在NgRx/Data中获取单一实体对象的实现方案
NgRx/Data本身并没有提供直接获取单一实体的entity$属性,但可以通过几种简单的方式实现需求,同时完全支持后续的update操作,包括实体内部嵌套列表的更新:
1. 基于entities$结合RxJS操作符筛选
这是最直接的方式,利用现有entities$ Observable,通过RxJS的filter和map操作符提取目标实体:
// 假设你已获取目标hero的id targetHeroId: number = 1; this.hero$ = this.heroService.entities$.pipe( // 确保实体列表已加载,避免初始空数组导致的undefined filter(entities => entities.length > 0), // 筛选出目标id对应的实体 map(entities => entities.find(hero => hero.id === this.targetHeroId)!) );
当你调用heroService.update()更新实体后,entities$会同步最新数据,hero$也会自动推送更新后的单一实体,包括内部嵌套的列表对象变化。
2. 结合getById与entityCache$监听
先通过getById()触发实体加载(如果未缓存),再从实体缓存中监听单个实体:
// 触发实体加载(若缓存中无该实体,会自动发起请求) this.heroService.getById(this.targetHeroId); this.hero$ = this.heroService.entityCache$.pipe( // 从缓存中提取指定id的hero map(cache => cache.heroes?.[this.targetHeroId]), // 过滤掉未加载完成的状态 filter(hero => !!hero) );
3. 自定义扩展EntityService(进阶复用)
如果项目多处需要获取单一实体,可以封装一个基础服务,统一添加entity$方法:
// 定义基础实体服务 export class BaseEntityService<T extends { id: number }> extends EntityService<T> { constructor(entityName: string, serviceElementsFactory: EntityServiceElementsFactory) { super(entityName, serviceElementsFactory); } // 添加获取单一实体的方法 entity$(id: number): Observable<T | undefined> { return this.entities$.pipe( map(entities => entities.find(item => item.id === id)) ); } } // 让你的HeroService继承基础服务 @Injectable() export class HeroService extends BaseEntityService<Hero> { constructor(serviceElementsFactory: EntityServiceElementsFactory) { super('Hero', serviceElementsFactory); } } // 使用时直接调用 this.hero$ = this.heroService.entity$(this.targetHeroId);
关于嵌套列表的更新
实体内部的嵌套列表完全支持通过update方法修改,只需传递包含最新嵌套数据的实体对象即可:
// 假设当前hero对象包含skills列表 const updatedHero = { ...currentHero, skills: [...currentHero.skills, { id: 3, name: '新技能' }] }; this.heroService.update(updatedHero);
更新完成后,前面定义的hero$会自动同步包含最新列表的实体数据。
内容的提问来源于stack exchange,提问作者Hello
相关产品推荐
相关产品推荐

