Angular Academy · 课时

实体与自定义功能

使用 withEntities 管理集合

第 4 / 4 课13 个步骤

实体与自定义功能 是 CoddyKit 上的免费 Angular Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Angular Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Angular Academy 课程共包含 4 节课。

管理集合

记录列表(待办事项、用户、产品)十分常见,因此 NgRx 提供了 withEntities,通过规范化状态和现成的更新函数来管理这些列表。

withEntities

withEntities 会将项目按 id 存储在 entityMap 中,并通过有序的 ids 数组维护顺序,同时公开一个包含列表的 entities computed 信号。

import { withEntities } from '@ngrx/signals/entities';

export const TodoStore = signalStore(
  withEntities<Todo>()
);
// store.entities() -> Todo[]

实体更新器

将更新辅助函数与 patchState 搭配使用:setAllEntities、addEntity、updateEntity、removeEntity。它们会保持映射和 id 顺序一致。

import { addEntity, removeEntity, updateEntity } from '@ngrx/signals/entities';

patchState(store, addEntity({ id: '1', title: 'A', done: false }));
patchState(store, updateEntity({ id: '1', changes: { done: true } }));
patchState(store, removeEntity('1'));

加载集合

获取数据后,使用 setAllEntities 替换整个集合;它会将数组规范化为映射和 ids。

import { setAllEntities } from '@ngrx/signals/entities';

load: rxMethod<void>(pipe(
  switchMap(() => api.getTodos()),
  tap(todos => patchState(store, setAllEntities(todos)))
))

自定义 idKey

如果实体的标识符不是 id,请传入一个选择器。之后,store 会使用该字段作为映射的键。

withEntities<User>(); // expects user.id
// custom key:
patchState(store, addEntity(user, { selectId: (u: User) => u.uuid }));

从实体派生数据

将 withEntities 与 withComputed 结合,在集合之上构建经过筛选或计数的读取模型。

withComputed(({ entities }) => ({
  remaining: computed(() => entities().filter(t => !t.done).length)
}))

什么是自定义 Feature

自定义 feature 是一个可复用的状态、computed 和 methods 集合,可以添加到多个 store 中。请使用 signalStoreFeature 创建它。

import { signalStoreFeature, withState } from '@ngrx/signals';

export function withLoading() {
  return signalStoreFeature(
    withState({ loading: false })
  );
}

复用 Feature

像添加内置 feature 一样,将自定义 feature 添加到任意 store 中。这就是共享加载标志或分页等横切关注点的方式。

export const TodoStore = signalStore(
  withLoading(),
  withEntities<Todo>()
);
// store.loading() now exists

包含方法的 Features

自定义 feature 可以包含 withMethods,以公开可复用的行为,例如 setLoading 辅助函数。

export function withLoading() {
  return signalStoreFeature(
    withState({ loading: false }),
    withMethods((store) => ({
      setLoading(loading: boolean) { patchState(store, { loading }); }
    }))
  );
}

可组合性

由于 features 只是返回 feature 描述对象的函数,因此您可以叠加多个 feature:withLoading()、withEntities() 以及应用专属的状态,最终全部合并到一个具有完整类型支持的 store 中。

泛型 Features

让功能具备泛型,以便适用于不同的实体类型。类型参数会一路传递,因此使用者可以继续享受完整的类型安全。

export function withSelected<T>() {
  return signalStoreFeature(
    withState({ selected: null as T | null })
  );
}

快速检查

检查您对实体和功能的掌握情况。

回顾

您使用 withEntities 管理了集合(规范化映射、更新器辅助函数和派生读取模型),并构建了可复用的泛型 signalStoreFeature 捆绑包,以便在多个存储之间共享状态、计算值和方法。

免费开始

用 AI 导师学习 HTML — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
38
课程
144

常见问题解答

「实体与自定义功能」课时是免费的吗?

是的 — 「实体与自定义功能」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Angular Academy 课程的其余内容,请升级到 CoddyKit PRO。 Angular Academy 课程共包含 4 节课。

「实体与自定义功能」这节课中我会学到什么?

使用 withEntities 管理集合 你通过在浏览器中直接运行的动手代码来练习 Angular Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Angular Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Angular Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「实体与自定义功能」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Angular Academy 课中编写并运行代码吗?

能。每节 Angular Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 创建 SignalStore
  2. 计算状态与方法
  3. 使用 rxMethod 处理异步任务
  4. 实体与自定义功能
← 返回 Angular Academy