最新消息:XAMPP默认安装之后是很不安全的,我们只需要点击左方菜单的 "安全"选项,按照向导操作即可完成安全设置。

Store 架構加入最簡單的 Reducer

XAMPP下载 admin 516浏览 0评论
 Store 架構加入最簡單的 Reducer
Reducer 是什麼?
如果對於 Observable 的 .reduce .scan 不熟的話,建議回頭看一下[ngrx/store -3] Observable 的 運算子 (Operator)。基本上.scan() 會一直持續做,而 reduce() 會等到 complete 時才一次將結果產生,而我們要的 Reducer 其實是一直循環持續做而且能用到前面的狀態,用 .scan() 來做 Reducer 是最適當的 Operator。

先從 Reducer 的輸出跟輸入看起

QQ截图20181009163654
 Reducer 是純函數
記得我們在 [ngrx/store-7] 純函數 (Pure Function) 以及 [ngrx/store-8] Javascript Mutable 跟 Immutable 資料型態談過純函數,如果您還沒看過這兩篇文章,建議您花些時間看一下,我們來寫一個最簡單的 Reducer

// reducer
const message = (state = [], action) => {
switch (action.type) {
case ‘ADD_MESSAGE’:
return […state, action.payload];
case ‘REMOVE_MESSAGE’:{
return state.filter(msg => msg.id

!= action.payload);
}
default:
return state;
}
}
這裡我們的狀態樹是一個物件的陣列,當增加一筆物件到陣列時(ADD_MESSAGE),我們使用擴展語法 … 拷貝原來陣列,再將新的物件放入陣列中,可以放在前面也可以放在後面,請記得在這裡我們不可以使用陣列的.push(),因為這樣做會改變原來的陣列,造成副作用。在 ngrx/store 並不會強制您這樣做,所以這是程式的紀律問題,有了這個紀律,往後系統複雜時,就比較不會產生莫名其妙的 Bug.

在刪除一筆資料時(REMOVE_MESSAGE),我們使用了 .filter(),這個陣列的 Operator 是可以使用的,因為它會產生新的陣列,不會改變原來的陣列。

將 Reducer 註冊 (register) 到 Store 中
接著我們將這個 Reducer 註冊給 Store 使用,整個程式如下

interface Action {
type: string;
payload?: any
}

class Dispatcher extends Rx.Subject<Action> {
dispatch(act) {
//console.log(‘got dispatch ‘, act.type);
this.next(act);
}
}

class Store extends Rx.BehaviorSubject<Action> {
constructor(private dispatcher, private reducer, initialState) {
super(initialState);
this.dispatcher
.do((v) => { /*console.log(‘do some effect for’, v.type) */})
.scan((s, v) => this.reducer(s, v), initialState)
.subscribe(state => {
super.next(state);  // new state, push to subscriber
});
}
dispatch(act) {  // delegate to dispatcher
this.dispatcher.dispatch(act);
}
// override next to allow store subscribe action$
next(act) {
this.dispatcher.dispatch(act);
}
}

// reducer
const message = (state = [], action) => {
switch (action.type) {
case ‘ADD_MESSAGE’:
return […state, action.payload];
case ‘REMOVE_MESSAGE’:{
return state.filter(msg => msg.id

!= action.payload);
}
default:
return state;
}
}

// instanciate new store
const initialState = [];
const dispatcher = new Dispatcher();
const store = new Store(dispatcher, message, initialState);

// add subscriber
const sub1 = store.subscribe(v => console.log(‘messages ===> ‘, v));

// start dispatch action
store.dispatch({type: ‘ADD_MESSAGE’, payload: {id: 1, message: ‘First Message’}});
store.dispatch({type: ‘ADD_MESSAGE’, payload: {id: 2, message: ‘Seconde Message’}});
store.dispatch({type: ‘REMOVE_MESSAGE’, payload: 2});
store.dispatch({type: ‘ADD_MESSAGE’, payload: {id: 3, message: ‘Third Message’}});

codepen

它的輸出如下

QQ截图20181009163709
 上面的程式架構還是延續原本的 Store 大架構,我們增加了一個參數 reducer,dispather 會將新的 Action 交給 .scan() 這個 Operator, 由 reducer 負責將就的狀態跟Action 處理完產生新的狀態。因為使用了 .scan(),整個循環會一直持續使用這個 reducer 來處理 Action,而且會用到前面的狀態。

實際上的 Reducer 會更複雜,這裡我們只有單一個狀態,單一個 Reducer, 那麼如果兩個以上的 Reducer 呢?還有如何處理狀態樹呢?我們接下來看。

转载请注明:XAMPP中文组官网 » Store 架構加入最簡單的 Reducer

您必须 登录 才能发表评论!