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

相关文章
相关标签/搜索