angular 11 ngrx/store 使用理解

声明

export interface AuthSate {
    site: ISite;
    cart: any;
}

export const authFeatureKey = 'auth';

export interface AppState {
    [authFeatureKey]: AuthSate;
}

export const initialState: AuthSate = {
    site: null, // 初始化时,必须设置值,未设置(undefined)的将无法通知
    cart: null,
};

// 定义根据action 修改方法
const authReducer = createReducer(
    initialState,
    on(setCart, (state, {cart}) => ({...state, cart})),
    on(setSite, (state, {site}) => ({...state, site})),

    on(clearAuth, state => Object.assign({}, initialState)), // 返回初始化
);

export function reducer(state: State<AppState> | undefined, action: Action) {
    return authReducer(state, action);
}

1234567891011121314151617181920212223242526272829

Actions

定义action 用于修改Store中的数据

export const setCart = createAction('[shop]SET_CART', props<{cart: ICart}>());
export const setSite = createAction('[shop]SET_SITE', props<{site: ISite}>());

12

相当于

export const setCart = (cart: ICart) => ({
    type: '[shop]SET_CART',
    payload: {cart},
});

12345

Selectors

定义 selector 用于获取数据

export const selectAuth = createFeatureSelector<AppState, AuthState>(authFeatureKey);

export const selectCart = createSelector(
    selectAuth,
    (state: AuthState) => state.cart
);

export const selectSite = createSelector(
    selectShop,
    (state: AuthState) => state.site
);

1234567891011

注册到程序中

注册根

app.module.ts

StoreModule.forRoot({
    [authFeatureKey]: reducer,
}),

123

这是必须的如果没有全局数据,则

StoreModule.forRoot({}),

1

也可以为某一个模块注册局部数据

StoreModule.forFeature(authFeatureKey, reducer),

1

使用

  1. 设置
export class AppComponent {
    constructor(
        private store: Store<AppState>,
    ) {

    }

    setSite() {
        this.store.dispatch(setSite({site: {}}));
    }
}

1234567891011

  1. 获取数据
export class AppComponent {
    constructor(
        private store: Store<AppState>,
    ) {
        this.store.select(selectSite).subscribe(site => {
            // TODO
        });
    }
}

123456789

特别注意

获取数据是一直实时更新的,除非取消订阅了。

更新的频率是依赖 reducer 的,把 reducer 看作一个对象,对象上的某一个属性更新了,会触发其他的属性更新事件

例如:

 this.store.select(selectSite).subscribe(site => {
    // 获取到的 site 的值
    this.store.dispatch(setCart({cart: {}})); // 这样会陷入死循环,更新了 cart 的值,也会触发 site 更新的事件
});

1234

转载请保留原文链接: https://zodream.cn/blog/id/191.html