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

@ngrx/store的createSelector()是否真的有必要使用?

关于NgRx选择器简洁性与可维护性的平衡方案

完全懂你的感受!这种直接用this.store.select('media', 'games')的选择器写法确实清爽到不行——不用写一堆createSelector,也不用额外导入任何东西,几行代码就能搞定状态读取,初期开发效率拉满。

但项目规模一上来,问题就暴露了:所有选择器都堆在media.selectors.ts里,文件会变得越来越臃肿,满屏都是那种只做简单取值的选择器。原本一句this.store.select('media', 'games')就能搞定的事,现在得先import * as fromMedia from '../media',再写this.store.select(fromMedia.getAllGamesSelector()),其他场景也是同理,感觉反而多了一层没必要的中间层,徒增工作量。

针对这个痛点,分享几个实用的平衡方案:

  • 模块化拆分选择器文件
    别把所有media相关的选择器都塞在一个文件里,可以按功能维度拆分,比如单独创建media-games.selectors.ts、media-movies.selectors.ts,每个文件只负责对应模块的选择器。这样不仅文件体积变小,找起来更方便,导入的时候也可以只导入需要的那个选择器,不用全量导入整个fromMedia模块。

  • 用类型安全工具兼顾简洁性
    如果担心字符串路径容易写错(毕竟没有类型提示),可以用NgRx的createFeatureSelector配合基础选择器,既保留接近原生的简洁性,又能获得类型检查:

    // media-games.selectors.ts
    import { createFeatureSelector, createSelector } from '@ngrx/store';
    import { MediaState } from './media.state';
    
    export const selectMediaState = createFeatureSelector<MediaState>('media');
    export const selectGames = createSelector(selectMediaState, state => state.games);
    

    使用时只需要导入selectGames即可:

    import { selectGames } from '../media/media-games.selectors';
    
    // ...
    this.store.select(selectGames);
    

    比全量导入清爽很多,同时还能避免路径拼写错误。

  • 根据场景灵活选择写法
    不用一刀切要求所有状态读取都用单独的选择器:对于简单的、全局复用率低的状态读取,完全可以继续用this.store.select('media', 'games')这种简洁写法;而对于那些需要复用、或者涉及复杂状态组合(比如多个切片合并计算)的场景,再单独抽离选择器。这样既能保留初期的开发效率,又不会让选择器文件变得臃肿不堪。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 02:22:33