站長資訊網
        最全最豐富的資訊網站

        Angular中使用ngrx/store進行狀態管理

        Angular中使用ngrx/store進行狀態管理

        簡介

        ngrx/store的靈感來源于Redux,是一款集成RxJS的Angular狀態管理庫,由Angular的布道者Rob Wormald開發。它和Redux的核心思想相同,但使用RxJS實現觀察者模式。它遵循Redux核心原則,但專門為Angular而設計。

        Angular中的狀態管理大部分可以被service接管,那么在一些中大型的項目中,這樣做的弊端就會顯露出來,其中之一就是狀態流混亂,不利于后期維護,后來便借鑒了redux的狀態管理模式并配上rxjs流式編程的特點形成了@ngrx/store這么一個作用于Angular的狀態管理工具.

        相關教程推薦:《angular教程》

        • StoreModule:
          StoreModule是@ngrx/store API中的一個模塊,它被用來在應用模塊中配置reducer。

        • Action:
          Action是狀態的改變。它描述了某個事件的發生,但是沒有指定應用的狀態如何改變。

        • Store:
          它提供了Store.select()和Store.dispatch()來與reducer協同工作。Store.select()用于選擇一個selector,
          Store.dispatch(
          {
          type:‘add’,
          payload:{name:‘111’}
          }
          )
          用于向reducer分發action的類型。

        @NgRx/Store 狀態管理的三個原則

        首先,@NgRx/Store 同樣遵守 Redux 的三個基本原則:

        • 單一數據源

        這個原則是整個單頁應用的狀態通過object tree(對象樹)的形式存儲在store 里面。
        這個定義十分抽象其實就是把所有需要共享的數據通過javascript 對象的形式存儲下來

        state ={     application:'angular app',     shoppingList:['apple', 'pear'] }
        • state is read-only(狀態只能是只讀形式)

        這個 ngrx/store 核心之一就是用戶不能直接修改狀態內容。 舉個例子,如果我們需要保存了登錄頁面狀態,狀態信息需要記錄登錄用戶的名字。 當登錄名字改變,我們不能直接修改狀態保存的用戶名字

        state={'username':'kat'}, //用戶重新登錄別的賬戶為tom state.username = 'tom'  //在ngrx store 這個行為是絕對不允許的
        • changes are made with pure functions(只能通過調用函數來改變狀態)

        由于不能直接需改狀態,ngrx/store 同時引入了一個叫做reducer(聚合器)的概念。通過reducer 來修改狀態。

        function reducer(state = 'SHOW_ALL', action) {     switch (action.type) {       	case 'SET_VISIBILITY_FILTER':         	return Object.assign({}, state  ,newObj);           default:         	return state           } 	}

        ngrx/store使用實例

        1.安裝@ngrx/store

        yarn add @ngrx/store

        2. 創建 state, action, reducer

        state 狀態:
        appstorestate.ts

        //下面是使用接口的情況, 更規范 export interface TaskList {   id: number;   text: string;   complete: boolean; }  export const TASKSAll: TaskList[] = [   {id: 1, text: 'Java Article 1', complete: false},   {id: 2, text: 'Java Article 2', complete: false} ]  export interface AppState {   count: number;   todos: TaskList;   // 如果要管理多個狀態,在這個接口中添加即可 }  //這個是不用接口的情況 // export interface AppState { //     count: number; //     todos: any; //     // 如果要管理多個狀態,在這個接口中添加即可 //   }

        reducer
        appstorereducer.ts

        // reducer.ts,一般需要將state,action,reducer進行文件拆分 import { Action } from '@ngrx/store';  export const INCREMENT = 'INCREMENT'; export const DECREMENT = 'DECREMENT'; export const RESET = 'RESET';  const initialState = 0; // reducer定義了action被派發時state的具體改變方式 export function counterReducer(state: number = initialState, action: Action) {   switch (action.type) {     case INCREMENT:       return state + 1;      case DECREMENT:       return state - 1;      case RESET:       return 0;      default:       return state;   } }

        actions

        如果需要把action 單獨提取出來, 參考 后面的
        5 如果想把action分離出來如何處理?

        3. 注冊store

        根模塊:
        app/app.module.ts

        import { NgModule } from '@angular/core'; import { StoreModule } from '@ngrx/store'; // StoreModule: StoreModule是@ngrx/storeAPI中的一個模塊, // 它被用來在應用模塊中配置reducer。  import {counterReducer} from './store/reducer';  @NgModule({   imports: [   	StoreModule.forRoot({ count: counterReducer }), // 注冊store   ], }) export class AppModule {}

        4. 使用store

        在組件或服務中注入store進行使用

        以 appmodulearticlearticle.component.ts 組件為例:

        // 組件級別 import { Component } from '@angular/core'; import { Store, select } from '@ngrx/store'; import { Observable } from 'rxjs'; import { INCREMENT, DECREMENT, RESET} from '../../store/reducer';  interface AppState {   count: number; }  @Component({   selector: 'app-article',   templateUrl: './article.component.html',   styleUrls: ['./article.component.css'] }) export class ArticleComponent  {   count: Observable<number>;    constructor(private store: Store<AppState>) { // 注入store     this.count = store.pipe(select('count'));      // 從app.module.ts中獲取count狀態流   }    increment() {     this.store.dispatch({ type: INCREMENT });   }    decrement() {     this.store.dispatch({ type: DECREMENT });   }    reset() {     this.store.dispatch({ type: RESET });   } }

        模板頁面:
        appmodulearticlearticle.component.html

        <div class="state-count">      <button (click)="increment()">增加Increment</button>     <div>Current Count: {{ count | async }}</div>     <button (click)="decrement()">減少Decrement</button>      <button (click)="reset()">Reset Counter</button> </div>

        這里使用了 管道符 async, 在子模塊里直接使用快報錯 , 如果在子模塊要實現 數據的雙向綁定也會報錯,具體原因參照 課件說明的 問題: The pipe ‘async’ could not be found?

        如何做到在模板頁面中不使用管道 來渲染頁面 ?

        修改如下:

        count: Observable<number>;  constructor(private store: Store<AppState>) { // 注入store     var stream = store.pipe(select('count'));      // 從app.module.ts中獲取count狀態流     stream.subscribe((res)=>{           this.count = res;       })   }

        為了管理方便, 一般會把 type , state, actions,reducers 分開來管理

        5 如果想把action分離出來如何處理?

        1. 新建 appstoreactions.ts 文件
        import { Injectable } from '@angular/core'; import { INCREMENT, DECREMENT, RESET } from './types';  @Injectable() export class CounterAction{     // Add=function(){}     Add(){         return { type: INCREMENT }     } }  // 就只這樣導出是不行的 // export function Add1(){ //     return { type: INCREMENT } // }
        1. 在根模塊 app.module.ts 注冊
        import {CounterAction} from './store/actions';  ...   providers: [CounterAction],
        1. 在組件中使用 – article.component.ts
        import {CounterAction} from '../../store/actions';  export class ArticleComponent implements OnInit {    constructor(     private action: CounterAction  //注入CounterAction     ) { }      increment() {     // this.store.dispatch({ type: INCREMENT });      //把 actions分離出去     this.store.dispatch(this.action.Add());         } }

        贊(0)
        分享到: 更多 (0)
        網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
        主站蜘蛛池模板: 国产精品无码无需播放器| 精品三级AV无码一区| 精品人妻人人做人人爽| 国产高清精品一区| 国产精品亚洲一区二区三区在线 | 免费视频精品一区二区| 91精品国产高清久久久久久io | 亚洲av无码国产精品色午夜字幕| 国产精品成| 杨幂国产精品福利在线观看| 91麻豆精品国产| 国产精品无套内射迪丽热巴| 无码人妻精品一区二区三区在线 | 亚欧乱色国产精品免费视频| 国产精品视频色视频| 久久91精品国产91久久户| 精品人妻久久久久久888| 无码人妻精品一区二区三区久久| 久久久久亚洲精品无码网址 | 69SEX久久精品国产麻豆| 久久亚洲美女精品国产精品| 亚洲精品无码鲁网中文电影| 亚洲国产精品成人午夜在线观看 | 久久亚洲国产午夜精品理论片| 岛国精品一区免费视频在线观看 | 中文字幕成人精品久久不卡| 2022国产精品不卡a| 精品免费人成视频app| 婷婷五月深深久久精品| 日韩精品视频一区二区三区| 亚洲AV无码精品色午夜在线观看| 亚洲午夜精品久久久久久浪潮| 人妻少妇精品久久| 日韩欧美一区二区三区中文精品| 老司机精品影院91| 色偷偷88欧美精品久久久| 亚洲А∨精品天堂在线| 亚洲欧美精品一区久久中文字幕 | 国产精品区一区二区三在线播放 | 国产精品看高国产精品不卡| freesexvideos精品老师毛多|