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的返回結果