Angular Signals 与 Effects

Angular 改变了处理响应式的方式。你不再需要 Zone.js 来检测每一个微小的变化。Signals 允许 Angular 仅更新 UI 中发生变化的特定部分。这使得你的应用运行得更快,并支持无 Zone (zoneless) 模式。

什么是 Signals?

Signal 是一个用于存储响应式值的容器。当值发生变化时,Angular 能够精确地知道需要更新模板的哪些部分。

  • signal():创建一个新的 signal。使用 .set() 替换值,或使用 .update() 基于当前值进行更新。
  • computed():创建一个只读的 signal。它从其他 signals 中派生出值。Angular 仅在你读取它时才进行计算,并缓存结果。
  • effect():当 signal 发生变化时运行代码。将其用于副作用,例如日志记录或手动 DOM 操作。

何时使用 Signals vs RxJS

你不需要二选一。你应该根据不同的任务同时使用两者。

使用 Signals 用于:

  • 持有 UI 状态。
  • 驱动模板渲染。
  • 替代 @Input()@Output()
  • 在无 Zone (zoneless) 应用中工作。

使用 RxJS 用于:

  • 处理 HTTP 或 WebSockets 等异步流。
  • 处理防抖 (debouncing) 或切换流等复杂逻辑。
  • 合并多个事件序列。

你可以使用 rxjs-interop 将它们连接起来:

  • toSignal():将 Observable 转换为 Signal。
  • toObservable():将 Signal 转换为 Observable。

新的无装饰器 API

Angular 17+ 引入了无需使用装饰器即可处理数据流的新方式。

  • input():用于接收来自父组件数据的只读 signal。
  • model():用于双向绑定的可写 signal。它取代了旧的 @Input()@Output() 模式。
  • output():一种从子组件向父组件发送事件的方式。它不是一个 signal,但它简化了你的代码。

为什么这比 React 更好

如果你了解 React,你会发现概念很相似,但执行方式不同。

  • 自动追踪:在 React 中,你必须在数组中列出依赖项。在 Angular 中,系统会自动追踪你使用了哪些 signals。你不会忘记添加依赖项。
  • 精确更新:React 通常会重新渲染整个组件。Angular signals 仅更新依赖于该值的特定 DOM 节点。
  • 无过期闭包 (Stale Closures):当你调用 signals 时,它们始终提供当前值。

来源:https://dev.to/atilla_baspinar_c5c68ec63/angular-signals-and-effects-35mn