Redux
被你們知道應該都是來自於 React
的出現,可是這篇文章會經過介紹一個 React
以外的例子,來讓你們理解 Redux
是什麼東西,到底還可以作點撒。javascript
我本身的理解是:java
Redux 是一個改變狀態(state)的模型,這個模型經過一個單向操做的方式來改變狀態,用數學符號的方式來理解我認爲應該是:
y = f(x)
,嗯,就是一個最簡單的函數模型。react
不過這樣說,有些人還會不理解,畢竟之前擼代碼不是這個樣子的,那麼咱們先反向的來獲取本身的理解。git
首先,咱們須要知道 Redux 有的如下幾個東西:redux
我以爲須要介紹清楚 Redux ,知道這三個就好了,至於還有一些函數我以爲都是調味料,這裏先不介紹。數組
好吧,如今我就把上面的數學函數模型語義的轉換一下(也許不必定對,可是可能暫時這樣理解,理解是一個過程):dom
newState = store(reducer)(state)
newState = reducer(state)
爲何這裏可能理解成兩個步驟呢?那是由於咱們能夠從不一樣的層面去認識 Redux,在第一步中個人理解是store裏面的東西(reducer)去改變了 state,而在第二步中,我以實際會起到做用的層面去理解,就是 reducer 去改變了 state。ide
好吧,來個對比:函數
y = f(x) newState = reducer(state)
最後我本身先得出一個結論:spa
f <=> reducer ( <=>: 表示等價的意思)
好吧,廢話就上面那麼多了,接下來我舉一個實際的例子來理一下本身對 Redux 的理解,這個例子是我在一篇文章中看到的,以爲不錯。
這裏咱們要實現的效果就是:
點擊飛機,讓飛機隨機移動到一個新的座標點
這裏咱們能夠理解爲:新座標[x1, y1] = f(原始座標[x0, y0])
1.首先咱們須要定義個 f
來修改座標
/** * reducer * @param state 座標狀態 * @param action 執行的行爲 */ function coordinates(state = [1, 1], action) { switch (action.type) { case CLICK: return [ state[0] + 40 * Math.random(), state[1] + 40 * Math.random() ] default: return state; } }
這個函數主要就是使初始座標 [1, 1] => [1 + random, 1 + random] 這樣返回一個全新的數組,這個全新的數組就是新的狀態。
2.咱們再將這個 f
函數給 Redux 的 Store 去管理
/** * 建立 Redux 的 Store(存儲器) */ let store = createStore(coordinates);
這個比較簡單,就是經過傳入 f
來建立一個 Store,對於 Redux 來講有且只有一個 Store,這個和 flux 有比較大的差異。
3.而後再定義一個行爲,使咱們可以經過 dispatch 調用這個行爲去改變 state
/** * action */ const CLICK = 'CLICK'; /** * @returns plainObject => action */ function click() { return { type: CLICK } }
在 Redux 中,只有經過 dispatch
方法去改變狀態,就是由於這樣,才讓咱們調試代碼變得簡單,復現 BUG 更加容易,由於它是單向的,順着一個方向在流動數據。
4.接下來就寫一下 dispatch
plane.events.onInputDown.add(() => { store.dispatch(click()) }, null);
先拋開其餘代碼,咱們剝離一下:
store.dispatch(click())
這樣就會去調用行爲,而後執行咱們上面定義的 coordinates
函數,返回一個新的座標
5.最後咱們再訂閱一下具體改變咱們飛機位置的業務代碼
上面的寫完後,咱們只是返回來狀態,可是還沒體現到飛機在場景下的移動效果。咱們可以經過
store.getState()
來獲取最新的當前狀態,其實在 Redux 源代碼裏面就是很簡單的一個函數:
function getState() { // 這裏的 currentState 是一個外部的變量,在 Store 的做用域下全局生效 return currentState; }
好吧,如今咱們讓飛機訂閱一下移動的函數:
/** * 定義 plane(飛機) 的移動 */ function movePlane(plane) { game.add.tween(plane).to({ x: store.getState()[0], y: store.getState()[1] }, 1000, 'Linear', true); } /** * 移動事件的訂閱 */ store.subscribe(movePlane.bind(null, plane));
你們會想,爲何我訂閱了就自動調用 movePlane 生效了呢?在 Redux 內部會調用當前的監聽器,源代碼以下,很簡單,監聽器就是一個數組來裝的,最後移出來執行一下:
function subscribe(listener) { var isSubscribed = true; ensureCanMutateNextListeners(); nextListeners.push(listener); // 而後會返回一個取消訂閱的函數,這裏省略 } function dispatch(action) { // 省略一些雜七雜八的異常處理代碼 try { isDispatching = true; currentState = currentReducer(currentState, action); } finally { isDispatching = false; } // 執行的代碼 var listeners = currentListeners = nextListeners; for (var i = 0; i < listeners.length; i++) { listeners[i](); } return action; }
好吧,這樣就是一個遊戲的流程來,在 Redux 的幫助下,很好的組織了代碼,優雅的完成了。執行代碼的流程是這樣的:
dispatch(click()) => update reducer => subscribe() => 飛機移動新位置
這個例子很好的解釋了脫離 React 的束縛,很純粹的 Redux,原文翻譯有點慢,乾脆就本身寫了一下。