我们非常高兴地向大家宣布NgRx框架的最新重大版本,这个版本包含了一些非常酷的新功能、修复了一些错误和其他更新。
此处省略内容
NgRx Signals 的新功能🚦NgRx Signals 在 v18 版本中作为稳定版本发布,这是一个从头开始使用 Angular Signals 构建的新库,选择性地与 RxJS 兼容,并内置实体管理功能。NgRx Signals 库持续获得高质量更新和改进,以提升开发者体验。
SignalStore 新特性
用户强烈要求的功能之一是在创建 SignalStore 时定义其 props。为此目的,添加了 withProps
基础特性,允许将静态属性或可观察对象定义为 SignalStore 的成员。
export const 书籍存储 = signalStore(
withEntities<书籍>(),
withRequestStatus(),
withProps(({ isFulfilled }) => ({
fulfilled$: toObservable(isFulfilled).pipe(filter(Boolean)),
})),
);
进入全屏 退出全屏
它也可以用来定义所有依赖项的地方,或者简化为:它也可以在一处定义所有的依赖项。
export const 商店 = signalStore(
withProps(() => ({
服务1: inject(服务1),
服务2: inject(服务2),
})),
withMethods(({ 服务1, 服务2 }) => ({
方法一() {
服务1.foo();
},
方法二() {
服务2.bar();
},
}))
);
全屏模式,退出全屏
新的 withProps
特性与新的 Angular Signals 特性(包括 resource
和 linkedSignal
)一起使用:
const booksStore = signalStore(
withProps(() => {
const bookResource = resource({
loader: () => Promise.resolve({ id: 1, title: "'指环王'" }),
});
return {
_bookResource: bookResource,
bookResource: bookResource.asReadonly(),
};
}),
);
点击全屏/退出全屏
上述将 bookResource 暴露为只读(read-only)资源,并同时保留可写的书资源。
接下来的例子将 prettyTitle
作为 linkedSignal
公开,并在内部保持其可写状态。
signalStore(
withState({ id: 1, title: "'<em>魔戒</em>'" }),
withProps((store) => ({
prettyTitle: linkedSignal(() => \`${store.id()}: ${state.store()}\`),
})),
);
全屏模式,点这里退出
新的 withProps
功能让你可以进一步扩展和完善 SignalStore,即使在使用 Angular Signals 时。感谢 Marko Stanimirović 为 NgRx Signals 的持续改进所做的贡献!
信号处理方法的工具函数
rxMethod
工具函数被引入,旨在提供一种将使用 RxJS 进行的异步任务与 Angular 信号连接的方法。我们还引入了 signalMethod
工具函数,它提供了与 rxMethod
相同的功能,但仅使用信号。
signalMethod
是一个工厂方法,用于处理信号或静态值的处理。
import { Component } from '@angular/core';
import { signalMethod } from '@ngrx/signals';
@Component({ /* ... */ })
export class NumbersComponent {
// 👉 这个方法接收一个 `number | Signal<number>` 类型的输入参数。
readonly logDoubledNumber = signalMethod<number>((num) => {
const double = num * 2;
console.log(double);
});
}
切换到全屏 退出全屏
乍一看,signalMethod
和 effect
可能看起来相同。然而,signalMethod
比 effect
具有三个明显的优势:
@Component({ /* ... */ })
export class NumbersComponent {
readonly num = signal(2);
readonly logDoubledNumberEffect = effect(() => {
console.log(this.num() * 2);
});
readonly logDoubledNumber = signalMethod<number>((num) => {
console.log(num * 2);
});
constructor() {
this.logDoubledNumber(this.num);
}
}
全屏显示 退出全屏
灵活的输入:输入参数可以是一个静态值,而不仅仅是信号。此外,处理器函数可以多次调用,每次传入不同的输入。
无需注入上下文:与需要注入上下文或注入器的效果不同,处理器函数可以在没有注入上下文的情况下被调用。
显式追踪:只追踪参数的信号,而处理器函数内的信号则不会被追踪。
阅读文档以了解更多关于 signalMethod 的信息。
开发模式检查中的状态变化检查
确保状态更新的不可变性对于Signal发出并触发必要的DOM更新、衍生信号或副作用至关重要。为解决这个问题,在开发环境中,patchState
函数会对状态进行深度冻结。
之前 :
const userState = signalState(initialState);
patchState(userState, (state) => {
state.user.firstName = '可变更改'; // 可变更改已生效
return state;
});
进入全屏。退出全屏。
然后,
const userState = signalState(initialState);
patchState(userState, (state) => {
state.user.firstName = '可变更'; // 这会在开发模式下抛出错误
return state;
});
点击全屏模式下,点击退出全屏
这确保状态变化是不可更改的,从而保持了高性能和最佳实践。
NgRx Store 在信号变化时分发操作NgRx Store 仍然是 Angular 应用程序中全局状态管理的默认选择之一。NgRx Store 之前引入了将状态作为信号选择的支持,现在提供了一种更人性化的读取信号分发操作的方法。
class BookComponent {
书籍ID = input.required<number>();
constructor(商店: Store) {
商店.dispatch(() => 加载书籍({ id: this.书籍ID() })));
}
}
全屏进入;退出全屏
dispatch
方法首次执行,并且每当 bookId
变化时也会执行。如果在注入上下文中调用 dispatch
,信号会被一直跟踪直到该上下文被销毁。在上面提到的例子中,这发生在 BookComponent
被销毁时。
当在组件的注入上下文之外调用 dispatch
时,信号会在整个应用中全局追踪。为了确保在这种情况下能够正确清理资源,需要将组件的 injector 传递给 dispatch
方法:
class BookComponent {
bookId = input.required<number>();
injector = inject(Injector);
store = inject(Store);
ngOnInit() {
// 在注入上下文之外执行
this.store.dispatch(
() => loadBook({ id: this.bookId() }),
{ injector: this.injector }
);
}
}
// 说明: `loadBook` 方法用于加载指定 ID 的书籍。
全屏切换,退出全屏
感谢Rainer Hahnekamp增加了这些功能!谢谢!
NgRx Signals,新的默认选项 🤝NgRx Signals 是一种从头开始的方法,用于以反应式方式管理状态,并且它支持可选的RxJS集成。它还提供了一些其他工具,以结构化方式帮助开发人员更好地处理Angular信号。目前,NgRx Signals 是推荐用于Angular应用程序中的本地状态管理库。对于新应用,建议从 NgRx SignalStore 开始。对于现有应用,考虑迁移到新的 @ngrx/signals
包。
随着 NgRx 在 Angular 中的使用越来越广泛,许多开发者和团队仍然需要指导来架构和构建企业级 Angular 应用。我们非常高兴地告诉大家,NgRx 团队将直接举办即将举行的研讨会!
从二月开始,我们将提供一到三天的全天工作坊,涵盖从 NgRx 的基础到最前沿的主题。不论您的团队是刚开始接触 NgRx 还是已经使用了一段时间——他们都将在这些工作坊中收获新的概念。
工作坊涵盖了使用NgRx Store和库来管理和维护全局状态,以及使用NgRx ComponentStore和NgRx Signals来管理局部状态。
访问我们的工作坊页面,并从我们即将举办的工作坊列表中报名。
新的文档网来啦 💅新的文档更新正在进行中,将从头开始使用AnalogJS构建,并采用全新的设计和经过更新的内容。这将确保为我们的用户提供最佳体验,并使用户更容易找到所需的信息。这还将使网站更易于维护和更新。由于我们是社区驱动的项目,我们还确保网站易于贡献。
特别感谢他在[@MikeRyanDev]为NgRx网站新版本做出的努力。
……
废弃和不兼容更改 💥此版本修复了一些错误,弃用了一些功能,并引入了一些不兼容变更。对于大多数弃用或不兼容变更,我们提供了一个自动迁移工具,它会在您将应用程序升级到最新版本时自动运行。
请查看版本 19 迁移指南,以获取有关迁移到最新版本的所有信息。您可以在我们的 GitHub 仓库中找到完整的CHANGELOG。
略
升级到 NgRx 19 🗓要开始使用 NgRx 19,请确认安装了以下最低版本(请参阅下方):
Angular 版本 19.x
Angular 命令行工具 版本 19.x
TypeScript 版本 5.5.x
RxJS 版本 6.5.x 或 7.5.x
NgRx 支持使用 Angular CLI 的 ng update
命令来更新 NgRx 包。要更新到最新版本,请运行以下命令:
ng 更新 @ngrx/store@19
全屏显示和退出全屏
如果你的项目使用了@ngrx/signals
,执行以下命令就可以了。
ng 更新:@ngrx/signals@19
全屏,退出全屏
潮牌商店和聊天室 🦺
你可以从我们的商店买到官方的 NgRx 周边产品哦!印有 NgRx 标志的 T 恤有多种尺寸、材质和颜色。未来我们还会增加更多周边产品,比如贴纸和磁铁等。快去我们的商店 (访问商店) 选购你的 NgRx 周边产品吧!
加入我们的Discord服务器,与NgRx社区的新老朋友们交流和学习。
为NgRx添砖加瓦 🥰
我们一直在努力改进文档,确保它们始终与 NgRx 框架用户的最新需求保持一致。为了帮助我们,你可以开始为 NgRx 做贡献,比如更新文档、修复问题等。如果你不确定从哪里开始,可以先看一下我们的贡献指南并观看 Jan-Niklas Wortmann 和 Brandon Roberts 制作的入门视频,他们可以帮你更好地开始。
感谢所有贡献者和支持者!
NgRx 仍然由社区驱动。设计、开发、文档编写和测试都由社区共同完成。访问我们的社区贡献者部分了解更多贡献者。
如果您想参与贡献,请访问我们的GitHub页面并浏览我们的公开问题,其中一些问题特别标记为适合新手贡献。我们还设有活跃的GitHub讨论,欢迎讨论新功能和增强功能。
我们想向金牌赞助商Nx表示衷心的感谢!Nx一直以来都是NgRx的忠实支持者,致力于支持他们依赖的开源项目,Nx认为NgRx是构建Angular应用的理想工具。
我们还想感谢我们的铜牌赞助商[Angular之家]!