Redux 能作什麼?

1、我先給一個 Redux 的定義

Redux 被你們知道應該都是來自於 React 的出現,可是這篇文章會經過介紹一個 React 以外的例子,來讓你們理解 Redux 是什麼東西,到底還可以作點撒。javascript

我本身的理解是:java

Redux 是一個改變狀態(state)的模型,這個模型經過一個單向操做的方式來改變狀態,用數學符號的方式來理解我認爲應該是:y = f(x),嗯,就是一個最簡單的函數模型。react

不過這樣說,有些人還會不理解,畢竟之前擼代碼不是這個樣子的,那麼咱們先反向的來獲取本身的理解。git

首先,咱們須要知道 Redux 有的如下幾個東西:redux

  • createStore
  • reducer
  • dispatch

我以爲須要介紹清楚 Redux ,知道這三個就好了,至於還有一些函數我以爲都是調味料,這裏先不介紹。數組

好吧,如今我就把上面的數學函數模型語義的轉換一下(也許不必定對,可是可能暫時這樣理解,理解是一個過程):dom

  1. 第一步:newState = store(reducer)(state)
  2. 第二步:newState = reducer(state)

爲何這裏可能理解成兩個步驟呢?那是由於咱們能夠從不一樣的層面去認識 Redux,在第一步中個人理解是store裏面的東西(reducer)去改變了 state,而在第二步中,我以實際會起到做用的層面去理解,就是 reducer 去改變了 state。ide

好吧,來個對比:函數

y = f(x)
newState = reducer(state)

最後我本身先得出一個結論:spa

f <=> reducer ( <=>: 表示等價的意思)

好吧,廢話就上面那麼多了,接下來我舉一個實際的例子來理一下本身對 Redux 的理解,這個例子是我在一篇文章中看到的,以爲不錯。

2、 先介紹一下這個例子的效果

飛機

這裏咱們要實現的效果就是:

點擊飛機,讓飛機隨機移動到一個新的座標點

這裏咱們能夠理解爲:新座標[x1, y1] = f(原始座標[x0, y0])

3、開始擼一個實例

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,原文翻譯有點慢,乾脆就本身寫了一下。

項目全部的代碼:https://git.oschina.net/fegg/redux-game

參考英文原文:http://atendesigngroup.com/blog/redux-outside-react

相關文章
相關標籤/搜索