首頁 > web前端 > js教程 > 一文快速了解Angular中的NgRx/Store框架

一文快速了解Angular中的NgRx/Store框架

青灯夜游
發布: 2021-06-30 11:24:01
轉載
4144 人瀏覽過

Angular中什麼是NgRx/Store框架?有什麼用?這篇文章就來帶大家了解NgRx/Store資料狀態管理框架,ngrx/store中的基本原則,透過範例了解該框架的簡單用法。

一文快速了解Angular中的NgRx/Store框架

【相關教學推薦:《angular教學》】

ngrx/store 是基於RxJS的狀態管理函式庫,靈感來自Redux。在NgRx中,狀態是由一個包含actionreducer的函數的映射組成的。 Reducer函數經由action的分發以及目前或初始的狀態而被調用,最後由reducer傳回一個不可變的狀態。

一文快速了解Angular中的NgRx/Store框架

狀態管理

在前端大型複雜Angular/AngularJS專案的狀態管理一直是個讓人頭痛的問題。在AngularJS(1.x版本)中,狀態管理通常由服務,事件,$rootScope混合處理。在Angular中(2 版本),元件通訊讓狀態管理變得清晰一些,但還是有點複雜,根據資料流向不同會用到很多方法。

ngrx/store中的基本原則

視圖層透過dispatch發起一個行為(action)、Reducer接收action,根據action.type類型來判斷執行、改變狀態、回傳一個新的狀態給store、由store更新state

一文快速了解Angular中的NgRx/Store框架

  • State(狀態) 是狀態(state)記憶體
  • Action (行為) 描述狀態的變化
  • Reducer(歸約器/歸約函數) 根據先前狀態以及當前行為來計算新的狀態,裡面的方法為純函數
  • 狀態用State的可觀察對象,Action的觀察者-Store來存取

Actions(行為)

Actions是訊息的載體,它會傳送資料到reducer,然後reducer更新storeActionsstore能接受資料的唯一方式。

ngrx/store裡,Action的介面是這樣的:

// actions包括行为类型和对应的数据载体
export interface Action {
  type: string;
  payload?: any;
}
登入後複製

type描述期待的狀態變化類型。例如,新增待辦 ADD_TODO,增加 DECREMENT 等。 payload是傳送到待更新store中的資料。 store派發action 的程式碼類似如下:

// 派发action,从而更新store
store.dispatch({
  type: 'ADD_TODO',
  payload: 'Buy milk'
});
登入後複製

Reducers(歸約器)

Reducers規定了行為對應的具體狀態變化。是純函數,透過接收前一個狀態和派發行為返回新物件作為下一個狀態的方式來改變狀態,新物件通常用Object.assign和擴展語法來實現。

// reducer定义了action被派发时state的具体改变方式
export const todoReducer = (state = [], action) => {
  switch(action.type) {
    case 'ADD_TODO':
      return [...state, action.payload];
    default:
      return state;
  }
}
登入後複製

開發時特別要注意函數的純性。因為純函數:

  • 不會改變它作用域外的狀態
  • 輸出只決定輸入
  • 相同輸入,總是得到相同輸出

Store(儲存)

store中儲存了應用程式中所有的不可變狀態。 ngrx/store中的storeRxJS狀態的可觀察對象,以及行為的觀察者。

可以利用Store來派發行為。也可以用Store的select()方法取得可觀察對象,然後訂閱觀察,在狀態變化之後做出反應。

上面我們描述的是基本流程。在實際開發過程中,會涉及API請求、瀏覽器儲存等非同步操作,就需要effectsserviceseffectsaction觸發,進行一些列邏輯後發出一個或多個需要加入到佇列的action,再由reducers處理。

一文快速了解Angular中的NgRx/Store框架

使用ngrx/store框架開發應用,始終只維護一個狀態,並減少對API的呼叫。

簡單範例

簡單介紹一個管理系統的登入模組。

建立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个原则定义相应的Actions

一文快速了解Angular中的NgRx/Store框架

  • reducers定义状态

    在文件auth.reducers.ts中创建状态,并初始化

    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实现数据交互(服务器)

    @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侦听从Store调度的动作,执行某些逻辑,然后分派新动作

    • 一般情况下只在这里调用API

    • 通过返回一个action给reducer进行操作来改变store的状态

    • effects总是返回一个或多个action(除非@Effect with {dispatch: false})

一文快速了解Angular中的NgRx/Store框架

  • @Effect()
    Login: Observable<any> = this.actions.pipe(
        ofType(AuthActionTypes.Login),   //执行Login响应
        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");
        })
    );
    登入後複製

    更多编程相关知识,请访问:编程视频!!

    以上是一文快速了解Angular中的NgRx/Store框架的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:juejin.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板