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 狀態:
app\\\\store\\\\state.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
app\\\\store\\\\reducer.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進行使用

以 app\\\\module\\\\article\\\\article.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 });
  }
}

模板頁面:
app\\\\module\\\\article\\\\article.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分離出來如何處理?新建 \\\\app\\\\store\\\\actions.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 }
// }

在根模塊 app.module.ts 注冊

import {CounterAction} from './store/actions';

... 

providers: [CounterAction],

在組件中使用 – 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()); 
    
  }
}

更多編程相關知識,可訪問:編程入門!!

更多關于云服務器域名注冊,虛擬主機的問題,請訪問三五互聯官網:www.shinetop.cn

贊(0)
聲明:本網站發布的內容(圖片、視頻和文字)以原創、轉載和分享網絡內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。郵箱:3140448839@qq.com。本站原創內容未經允許不得轉載,或轉載時需注明出處:三五互聯知識庫 » Angular中使用ngrx/store進行狀態管理

登錄

找回密碼

注冊