ngrx在項目中常的一些方法,淺顯易懂,一看就會

select:this.store.pipe(select('countInfo')) // 獲取這個狀態的值
dispatch:this.store.dispatch(increment()); // 觸發對應的事件來更改countInfo的值

app/ngrx目錄 

 header.action.ts

import { createAction,props } from '@ngrx/store';

export const increment = createAction('[Counter Component] Increment');
export const decrement = createAction('[Counter Component] Decrement');
export const reset = createAction(
    '[Counter Component] Reset',
    props<{count:number}>()
);

header.reducer.ts

import { createReducer, on } from '@ngrx/store';
import { increment, decrement, reset } from '../actions/header.action';

export interface State {
    count:number
};
export const initialState: State = {count:0};

const _counterReducer = createReducer(initialState,
  on(increment, state => ({...state,count:state.count-1})), // 計數器+1
  on(decrement, state => ({...state,count:state.count+1})), // 計數器-1
  on(reset, (state,action) => ({...state,count:action.count})), // 計數器重置
);

export function counterReducer(state, action) {
  return _counterReducer(state, action);
}

 app/ngrx/reducers/index.ts

import { NgModule } from '@angular/core';
import { StoreModule } from '@ngrx/store';
import * as counterReducer from 'src/app/ngrx/reducers/header.reducer';
// import * as loginReducer from 'src/app/ngrx/reducers/login.reducer';

export interface State {
    countInfo:counterReducer.State,
    //userInfo:loginReducer.State
}
  
const initialState: State = {
    countInfo: counterReducer.initialState,
    //userInfo: loginReducer.initialState
};
  
const reducers = { 
    countInfo: counterReducer.counterReducer,
   // userInfo:loginReducer.loginReducer
 }

@NgModule({
    imports: [
        StoreModule.forRoot(reducers),
        // StoreModule.forFeature('countInfo',counterReducer.counterReducer),
        // StoreModule.forFeature('userInfo',loginReducer.loginReducer),
    ]
})
export class AppStoreModule {}


最後記得在app.module.ts中 imports:[AppStoreModule]

在具體的組件中使用使用,然後就可以看到頁面有幾個按鈕,點擊不同的按鈕就可以實現count 的增減和重置:

/* .ts文件 */ 
import * as fromReducer from 'src/app/ngrx/reducers/index';
constructor(private store:Store<fromReducer.State>) { 
      this.countInfo$ = store.pipe(select('countInfo'));
     //this.userInfo$.subscribe(item=>console.log(item))
}
increment() {this.store.dispatch(increment());}
decrement() {this.store.dispatch(decrement()); }
this.store.dispatch(reset({count:10}));

/*.html文件*/
<div>{{ (countInfo$ | async).count }}</div>
<button id="increment" (click)="increment()">Increment</button>
<button id="decrement" (click)="decrement()">Decrement</button>
<button id="reset" (click)="reset()">Reset Counter</button>

上面的代碼:
forRoot():註冊根狀態:
應用程序的狀態被定義爲一個大對象。註冊化簡函數以管理部分狀態時,只會在對象中定義具有關聯值的鍵。要Store在應用程序中註冊全局StoreModule.forRoot()變量,請將該方法與定義狀態的鍵/值對映射一起使用。這些StoreModule.forRoot()註冊器爲您的應用程序註冊了全局提供程序,包括Store您注入到組件和服務中的服務,以分派操作並選擇狀態
forFeature() :註冊功能狀態:
功能狀態的行爲與根狀態相同,但是允許您在應用程序中使用特定功能區域定義它們。您的狀態是一個大對象,功能狀態在該對象中註冊了其他鍵和值。
如果要使用StoreModule.forFeature,需要再app.module.ts裏面imports:[StoreModule.forRoot({})] 

 

createSelector:選擇器 

參考:https://ngrx.io/guide/store/selectors

createSelector會跟蹤調用選擇器函數的最新參數。因爲選擇器是純函數,所以當參數匹配時可以返回最後的結果,而無需重新調用選擇器函數。這可以提供性能優勢,尤其是對於執行昂貴計算的選擇器而言。這種做法稱爲記憶

對一個狀態使用選擇器
 app/ngrx/reducers/index.ts增加如下代碼

import { createSelector } from '@ngrx/store';
import * as counterReducer from 'src/app/ngrx/reducers/header.reducer';

export interface State {
    countInfo:counterReducer.State,
}

// 在State狀態中篩選出countInfo
export const selectCountInfo = (state: State) => state.countInfo;

// 篩選出count   調用 store.pipe(select((()=>fromReducer.selectFeatureCount)()))
export const selectFeatureCount = createSelector(
    selectCountInfo,
  (state: counterReducer.State) => state.count
);

在組件中使用,結果,實時輸出count的結果

import * as fromReducer from 'src/app/ngrx/reducers/index';
constructor(private store:Store<fromReducer.State>) { 
      ...
      this.selectFeatureCount$ = store.pipe(select((()=>fromReducer.selectFeatureCount)()));
      this.selectFeatureCount$.subscribe(item=>console.log(item));
}

對多個狀態使用選擇器

createSelector可用於選擇從狀態的一些數據基於相同狀態的幾個切片。該createSelector功能最多可使用8個選擇器功能,以進行更完整的狀態選擇。例如,假設您有一個selectedUser處於狀態的對象。您還具有allBooks一系列的書本對象。您想顯示當前用戶的所有圖書。您可以createSelector用來實現這一目標。即使您在中更新了可見的圖書,它們也會始終保持最新狀態allBooks。如果選擇一本,它們將始終顯示屬於您用戶的圖書,而當未選擇任何用戶時,它們將顯示所有圖書。結果將只是狀態的另一部分過濾掉您的某些狀態。而且它將永遠是最新的。

import { createSelector } from '@ngrx/store';

export interface User {
  id: number;
  name: string;
}

export interface Book {
  id: number;
  userId: number;
  name: string;
}

export interface AppState {
  selectedUser: User;
  allBooks: Book[];
}

export const selectUser = (state: AppState) => state.selectedUser;
export const selectAllBooks = (state: AppState) => state.allBooks;

export const selectVisibleBooks = ()=> createSelector(
  selectUser,
  selectAllBooks,
  (selectedUser: User, allBooks: Book[]) => {
    if (selectedUser && allBooks) {
      return allBooks.filter((book: Book) => book.userId === selectedUser.id);
    } else {
      return allBooks;
    }
  }
);

/*
上面代碼中,是對兩個狀態操作,在allBooks數組中篩選userId等於selectedUser.id:
(selectedUser: User, allBooks: Book[]) => {...} 
selectedUser爲(state: AppState) => state.selectedUser的返回結果
allBooks爲(state: AppState) => state.allBooks的返回結果
*/


// 在組件中使用:
import * as fromReducer from 'src/app/ngrx/reducers/index';
constructor(private store:Store<fromReducer.State>) { 
      ...
      this.selectBooks$ = store.pipe(select(fromReducer.selectVisibleBooks()));
      this.selectBooks$.subscribe(item=>console.log(item));
}

使用selecotr props

 app/ngrx/reducers/index.ts新增如下代碼

export interface State {
    countInfo:counterReducer.State,
}

export const getCount = () => 
createSelector(
   (state, props) => state.countInfo[props.id],
   (counter, props) => counter * props.multiply
);

// props.id 和props.multiply 都是傳進來的;
// (counter, props)=>... 中的counter爲上一個(state, props) => state.countInfo[props.id]的結果
// 如:當state.countInfo[props.id]等於2的時候,counter等於2

在組件中使用:

  constructor(private store:Store<fromReducer.State>) { 
      this.counter$ = store.pipe(select(fromReducer.getCount(), { id: 'count', multiply: 2 }));
      this.counter$.subscribe(item=>console.log(item));
  }

// this.counter$結果:
// 當count爲0的時候(counter$ | async )  0
// 當count爲2的時候(counter$ | async )  4

createFeatureSelector
createFeatureSelector是用於返回頂級要素狀態的便捷方法。它爲狀態要素切片返回類型選擇器函數。

// 直接返回State的類型爲counterReducer.State的countInfo
export const selectFeature = createFeatureSelector<State, counterReducer.State>('countInfo');
 
export const selectFeatureCounts = ()=> createSelector(
  selectFeature,
  (state: counterReducer.State) => state.count
);

// (state: counterReducer.State) => state.count中state爲selectFeature的返回結果

源碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章