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