溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Angular中NgRx/Store框架怎么用

發(fā)布時(shí)間:2021-06-30 13:42:55 來(lái)源:億速云 閱讀:233 作者:小新 欄目:web開(kāi)發(fā)

這篇文章將為大家詳細(xì)講解有關(guān)Angular中NgRx/Store框架怎么用,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

ngrx/store 是基于RxJS的狀態(tài)管理庫(kù),其靈感來(lái)源于Redux。在NgRx中,狀態(tài)是由一個(gè)包含actionreducer的函數(shù)的映射組成的。Reducer函數(shù)經(jīng)由action的分發(fā)以及當(dāng)前或初始的狀態(tài)而被調(diào)用,最后由reducer返回一個(gè)不可變的狀態(tài)。

Angular中NgRx/Store框架怎么用

狀態(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ì)用到很多方法。

ngrx/store中的基本原則

視圖層通過(guò)dispatch發(fā)起一個(gè)行為(action)、Reducer接收action,根據(jù)action.type類型來(lái)判斷執(zhí)行、改變狀態(tài)、返回一個(gè)新的狀態(tài)給store、由store更新state。

Angular中NgRx/Store框架怎么用

  • 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(行為)

Actions是信息的載體,它發(fā)送數(shù)據(jù)到reducer,然后reducer更新storeActionsstore能接受數(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(歸約器)

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ǔ))

store中儲(chǔ)存了應(yīng)用中所有的不可變狀態(tài)。ngrx/store中的storeRxJS狀態(tài)的可觀察對(duì)象,以及行為的觀察者。

可以利用Store來(lái)派發(fā)行為。也可以用Store的select()方法獲取可觀察對(duì)象,然后訂閱觀察,在狀態(tài)變化之后做出反應(yīng)。

上面我們描述的是基本流程。在實(shí)際開(kāi)發(fā)過(guò)程中,會(huì)涉及API請(qǐng)求、瀏覽器存儲(chǔ)等異步操作,就需要effectsserviceseffectsaction觸發(fā),進(jìn)行一些列邏輯后發(fā)出一個(gè)或者多個(gè)需要添加到隊(duì)列的action,再由reducers處理。

Angular中NgRx/Store框架怎么用

使用ngrx/store框架開(kāi)發(fā)應(yīng)用,始終只維護(hù)一個(gè)狀態(tài),并減少對(duì)API的調(diào)用。

簡(jiǎn)單示例

簡(jiǎn)單介紹一個(gè)管理系統(tǒng)的登錄模塊。

創(chuàng)建Form表單

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表單

NGRX Store

按照上述的4個(gè)原則定義相應(yīng)的Actions

Angular中NgRx/Store框架怎么用

  • 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})

Angular中NgRx/Store框架怎么用

  • @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)把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(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)容。

AI