You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 16中NgRx选择器结合计算信号的正确用法及逻辑位置

Angular 16 Signals 替代 NgRx Selectors 的正确实现与性能分析

场景背景

我正在使用Angular 16并刚开始使用Signals,它们让NgRx的使用体验更佳。过渡过程中,遇到可抽象为以下场景的问题:

原来使用NgRx Selectors的实现代码:

const state = {
 someArray: [1, 5, 7]
}

export const selectArray = createSelector(
  state,
  (state) => state.someArray
);

export const selectFirst = createSelector(
  selectArray,
  (someArray) => someArray[0]
);

export const selectLast = createSelector(
  selectArray,
  (someArray) => someArray[state.someArray.length-1]
);

export const selectLastMinusFirst = createSelector(
  [selectFirst, selectLast],
  (first, last) =>
    last - first
);

现在尝试用Signals在组件中重写,有两种写法:

写法一:计算信号(computed)

const someArray: Signal<number[]> = this.store.selectSignal(Selectors.SelectArray)
const first: Signal<number> = computed(() => someArray()[0]);
const last: Signal<number> = computed(() => someArray()[state.someArray.length-1]);
const lastMinusFirst: Signal<number> = computed(() => last() - first());

写法二:effect实现

let first = 0;
let last = 0;
let lastMinusFirst = 0;

const someArray: Signal<number[]> = this.store.selectSignal(Selectors.SelectArray)

constructor() {
  effect(() => {
    if(someArray().length) {
      this.first = someArray()[0];
      this.last = someArray()[someArray().length - 1];
      this.lastMinusFirst = this.last - this.first;
    }
  });
}

问题

请问正确的实现方式是什么?正如官方文档所述,计算信号因懒加载和缓存机制是否更高效?


解答

正确实现方式

优先选择**计算信号(computed)**的写法,同时需要修正代码中的错误:原写法里的last信号误用了外部的state变量,应该直接使用someArray()的长度来获取最后一项。修正后的代码如下:

const someArray: Signal<number[]> = this.store.selectSignal(Selectors.SelectArray);
const first: Signal<number> = computed(() => someArray()[0]);
const last: Signal<number> = computed(() => someArray()[someArray().length - 1]);
const lastMinusFirst: Signal<number> = computed(() => last() - first());

而effect的写法不适合这个场景,原因如下:

  • effect的设计初衷是处理副作用操作(比如DOM修改、API请求、日志输出等),并非用于派生状态。
  • 手动维护first、last这类变量会增加状态同步的复杂度,容易出现不一致的情况,远不如计算信号自动同步依赖的方式可靠简洁。

计算信号的性能优势

计算信号确实比effect写法更高效,核心得益于它的懒加载和缓存机制:

  • 懒加载:计算信号只有在被订阅(比如在模板中使用、被其他计算信号或effect引用)时,才会执行计算逻辑,避免无意义的资源消耗。
  • 缓存机制:只有当它依赖的信号(此处为someArray)发生变化时,计算信号才会重新计算并更新结果;如果依赖未变化,直接返回缓存的结果。而effect会在依赖每次变化时都执行内部逻辑,哪怕结果没有被使用,会造成不必要的计算浪费。

此外,计算信号的写法更贴合Signals的设计理念,状态派生逻辑清晰,无需手动维护状态同步,能有效减少出错概率。


内容的提问来源于stack exchange,提问作者sili3011

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 16:34:57