ngrx / store 使用记录
项目中的组件通信,原以为使用 EventEmitter,再通过 subscribe 订阅传递消息
结果找了一圈都没发现相关代码,倒是一直有 this.store.patch 这种代码:
百度了一下,发现是一种状态管理工具(孤陋寡闻了):
Angular中的状态管理大部分可以被service接管,那么在一些中大型的项目中,这样做的弊端就会显露出来,其中之一就是状态流混乱,不利于后期维护,后来便借鉴了 redux 的状态管理模式并配上 rxjs 流式编程的特点形成了 @ngrx/store 这么一个作用于 Angular 的状态管理工具。
于是乎学了一下,不过百度出来的相关文章多数写的都比较笼统,只能做参考用,照搬代码总是会少些关键信息,最后还是结合项目,整理出了具体使用方法,这里做下记录,以备后需。基础的知识点这里就不描述了,百度一下有很多,直接记录代码(先图后码):
1、首先代码层次比较简单,用于测试,主要有三个文件,actions、reducer、state:
2、action 描述状态变化,对于每一个 action, 都要有一个继承自 Action 的类:
3、Reducer 描述了任何一个 action 所对应的应用的 state 将怎样变化
4、State是一个单独的不可变的数据结构(可以理解为一个全局的共享数据集);创建选择器,用于绑定store数据。
5、配置 reducer ,(这里的 info 应该是对应 AppState 里的 info 字段):
6、至此准备工作完成,引入 store,更新数据使用 dispatch:
7、获取数据使用 pipe:
最后别忘了销毁:
界面效果:
代码:
actions.ts
import { Action } from "@ngrx/store"; /** * NgRx的Action描述了状态的变化。对于每一个action,我们都需要创建一个继承自Action的类, * 同时定义其 type 和 payload(payload是个可选参数)。 */ export enum ActionTypes { ZOOM_IN = 'ZOOM_IN', ZOOM_OUT = 'ZOOM_OUT', ADD_OBJ = 'ADD_OBJ', } // 每个action其实就定义了一个类型,action的类型 export class ZoomInAction implements Action { readonly type = ActionTypes.ZOOM_IN; constructor() { } } export class ZoomOutAction implements Action { readonly type = ActionTypes.ZOOM_OUT; constructor() { } } export class AddObjAction implements Action { readonly type = ActionTypes.ADD_OBJ; constructor(public newObj: object) { } } // 导出对应的actions export type ActionUnion = ZoomInAction | ZoomOutAction | AddObjAction;
reducer.ts
// 引入action中定义的变量 import { ActionTypes, ActionUnion } from "./actions"; import { InfoState } from "./state"; /** * Reducer描述了任何一个action所对应的应用的state将怎样变化。 */ // 默认的初始数据,在状态改变过程中新状态将会覆盖默认数据 const defaultSettings: InfoState = { zoom: 1, object: {}, }; /** * 响应操作请求。(module 注册此 reducer) * @param state * @param action */ export function designerMimicsReducer( state: InfoState = defaultSettings, action: ActionUnion ) { switch (action.type) { case ActionTypes.ZOOM_IN: return { ...state, zoom: state.zoom + 0.2 }; case ActionTypes.ZOOM_OUT: return { ...state, zoom: state.zoom - 0.2 }; case ActionTypes.ADD_OBJ: return { ...state, object: action.newObj }; default: return state; } }
state.ts
import { createSelector } from "@ngrx/store"; export interface InfoState { zoom: number; object: object; } /* 要记录的变量列表 */ export interface AppState { info: InfoState; } export const selectInfo = (state: AppState) => state.info; export const selectZoom = createSelector( selectInfo, (state: InfoState) => state && state.zoom ); export const selectObject = createSelector( selectInfo, (state: InfoState) => state && state.object )