您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)Angular中NgRx/Store框架怎么用,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
ngrx/store
是基于RxJS
的狀態(tài)管理庫(kù),其靈感來(lái)源于Redux
。在NgRx
中,狀態(tài)是由一個(gè)包含action
和reducer
的函數(shù)的映射組成的。Reducer
函數(shù)經(jīng)由action
的分發(fā)以及當(dāng)前或初始的狀態(tài)而被調(diào)用,最后由reducer
返回一個(gè)不可變的狀態(tài)。
在前端大型復(fù)雜Angular/AngularJS
項(xiàng)目的狀態(tài)管理一直是個(gè)讓人頭疼的問(wèn)題。在AngularJS(1.x版本)中,狀態(tài)管理通常由服務(wù),事件,$rootScope
混合處理。在Angular中(2+版本),組件通信讓狀態(tài)管理變得清晰一些,但還是有點(diǎn)復(fù)雜,根據(jù)數(shù)據(jù)流向不同會(huì)用到很多方法。
視圖層通過(guò)dispatch
發(fā)起一個(gè)行為(action)、Reducer
接收action
,根據(jù)action.type
類型來(lái)判斷執(zhí)行、改變狀態(tài)、返回一個(gè)新的狀態(tài)給store
、由store
更新state
。
State
(狀態(tài)) 是狀態(tài)(state
)存儲(chǔ)器
Action
(行為) 描述狀態(tài)的變化
Reducer
(歸約器/歸約函數(shù)) 根據(jù)先前狀態(tài)以及當(dāng)前行為來(lái)計(jì)算出新的狀態(tài),里面的方法為純函數(shù)
狀態(tài)用State
的可觀察對(duì)象,Action
的觀察者——Store
來(lái)訪問(wèn)
Actions
是信息的載體,它發(fā)送數(shù)據(jù)到reducer
,然后reducer
更新store
。Actions
是store
能接受數(shù)據(jù)的唯一方式。
在ngrx/store
里,Action
的接口是這樣的:
// actions包括行為類型和對(duì)應(yīng)的數(shù)據(jù)載體 export interface Action { type: string; payload?: any; }
type
描述期待的狀態(tài)變化類型。比如,添加待辦 ADD_TODO
,增加 DECREMENT
等。payload
是發(fā)送到待更新store
中的數(shù)據(jù)。store
派發(fā)action
的代碼類似如下:
// 派發(fā)action,從而更新store store.dispatch({ type: 'ADD_TODO', payload: 'Buy milk' });
Reducers
規(guī)定了行為對(duì)應(yīng)的具體狀態(tài)變化。是純函數(shù),通過(guò)接收前一個(gè)狀態(tài)和派發(fā)行為返回新對(duì)象作為下一個(gè)狀態(tài)的方式來(lái)改變狀態(tài),新對(duì)象通常用Object.assign
和擴(kuò)展語(yǔ)法來(lái)實(shí)現(xiàn)。
// reducer定義了action被派發(fā)時(shí)state的具體改變方式 export const todoReducer = (state = [], action) => { switch(action.type) { case 'ADD_TODO': return [...state, action.payload]; default: return state; } }
開(kāi)發(fā)時(shí)特別要注意函數(shù)的純性。因?yàn)榧兒瘮?shù):
不會(huì)改變它作用域外的狀態(tài)
輸出只決定于輸入
相同輸入,總是得到相同輸出
store
中儲(chǔ)存了應(yīng)用中所有的不可變狀態(tài)。ngrx/store
中的store
是RxJS
狀態(tài)的可觀察對(duì)象,以及行為的觀察者。
可以利用Store
來(lái)派發(fā)行為。也可以用Store的select()
方法獲取可觀察對(duì)象,然后訂閱觀察,在狀態(tài)變化之后做出反應(yīng)。
上面我們描述的是基本流程。在實(shí)際開(kāi)發(fā)過(guò)程中,會(huì)涉及API請(qǐng)求、瀏覽器存儲(chǔ)等異步操作,就需要effects
和services
,effects
由action
觸發(fā),進(jìn)行一些列邏輯后發(fā)出一個(gè)或者多個(gè)需要添加到隊(duì)列的action
,再由reducers
處理。
使用ngrx/store框架開(kāi)發(fā)應(yīng)用,始終只維護(hù)一個(gè)狀態(tài),并減少對(duì)API的調(diào)用。
簡(jiǎn)單介紹一個(gè)管理系統(tǒng)的登錄模塊。
1、增加組件:LoginComponent
,主要就是布局,代碼為組件邏輯
2、定義用戶:User Model
export class User { id: number; username: string; password: string; email: string; avatar: string; clear(): void { this.id = undefined; this.username = ""; this.password = ""; this.email = ""; this.avatar = "./assets/default.jpg"; } }
3、添加表單:在組件LoginComponent
增加Form
表單
按照上述的4個(gè)原則定義相應(yīng)的Actions
reducers
定義狀態(tài)
在文件auth.reducers.ts
中創(chuàng)建狀態(tài),并初始化
export interface AuthState { isAuthenticated: boolean; user: User | null; errorMessage: string | null; } export const initialAuthState: AuthState = { isAuthenticated: false, user: null, errorMessage: null };
actions
定義行為
export enum AuthActionTypes { Login = "[Auth] Login", LoginSuccess = "[Auth] Login Success", LoginFailure = "[Auth] Login Failure" } export class Login implements Action { readonly type = AuthActionTypes.Login; constructor(public payload: any) {} }
service
實(shí)現(xiàn)數(shù)據(jù)交互(服務(wù)器)
@Injectable() export class AuthService { private BASE_URL = "api/user"; constructor(private http: HttpClient) {} getToken(): string { return localStorage.getItem("token"); } login(email: string, pwd: string): Observable<any> { const url = `${this.BASE_URL}/login`; return this.http.post<User>(url, { email, pwd }); } }
effects偵聽(tīng)從Store調(diào)度的動(dòng)作,執(zhí)行某些邏輯,然后分派新動(dòng)作
一般情況下只在這里調(diào)用API
通過(guò)返回一個(gè)action給reducer進(jìn)行操作來(lái)改變store的狀態(tài)
effects總是返回一個(gè)或多個(gè)action(除非@Effect with {dispatch: false})
)
@Effect() Login: Observable<any> = this.actions.pipe( ofType(AuthActionTypes.Login), //執(zhí)行Login響應(yīng) map((action: Login) => action.payload), switchMap(payload => { return this.authService.login(payload.email, payload.password).pipe( map(user => { return new LoginSuccess({ uid: user.id, email: payload.email }); }), catchError(error => { return of(new LoginFailure(error)); }) ); }) ); //失敗的效果 @Effect({ dispatch: false }) LoginFailure: Observable<any> = this.actions.pipe(ofType(AuthActionTypes.LoginFailure)); //成功的效果 @Effect({ dispatch: false }) LoginSuccess: Observable<any> = this.actions.pipe( ofType(AuthActionTypes.LoginSuccess), tap(user => { localStorage.setItem("uid", user.payload.id); this.router.navigateByUrl("/sample"); }) );
關(guān)于“Angular中NgRx/Store框架怎么用”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。