NGXS中@Select装饰器的lambda选择器如何确定对应的状态来源?
NGXS lambda选择器实现逻辑
首先明确核心前提:NGXS采用单一全局根状态树的设计,所有通过@State()装饰器注册的状态切片,最终都会挂载到这个全局根对象上,挂载的key就是你定义State时传入的name配置项。
你提到的@Select(state => state.zoo.animals)写法的运行逻辑非常直白,没有任何隐式的状态绑定逻辑,完整流程如下:
- 第一步:状态注册阶段,你通过
NgxsModule.forRoot([ZooState])或者NgxsModule.forFeature([ZooState])注册ZooState时,NGXS会读取ZooState上@State装饰器的name配置(也就是示例里的zoo),把该状态切片挂载到全局根状态的对应key下。
假设你的ZooState定义如下:
此时全局根状态的结构就是:interface ZooStateModel { animals: string[]; } @State<ZooStateModel>({ name: 'zoo', // 这里的name决定了状态切片在根状态上的key defaults: { animals: [] } }) export class ZooState {}{ zoo: { // 对应ZooState的name配置 animals: [] }, // 其他注册的状态切片 // user: {...}, // order: {...} } - 第二步:
@Select装饰器接收到你传入的lambda函数时,不会做任何预解析或者绑定操作,只是把这个函数作为选择器存储下来。 - 第三步:组件初始化后,当你订阅被
@Select装饰的可观察对象时,NGXS的Store服务会在每次全局状态更新时,把完整的全局根状态对象作为参数传入你写的lambda函数,执行函数得到返回值后,将返回值作为流的最新值推送给订阅者。
也就是说,你写的lambda里的state参数从始至终都是完整的全局根状态,根本不需要框架识别绑定到某个具体的State类,你可以直接在lambda里访问根状态上的任意属性。
注意事项
这种写法的灵活性很高,但也有缺陷:如果后续你修改了ZooState的name配置,所有写了state.zoo.xxx的lambda选择器都需要同步修改路径,否则会读取不到值。而直接传入State类或者State类上的静态选择器的写法,会由框架自动根据State类匹配对应的状态切片,不存在这个问题。
内容的提问来源于stack exchange,提问作者Isochronous
相关产品推荐
相关产品推荐

