redux里面的概念很多,有Action、ActionCreator、reducer、store、middleware、Provider、Connect……概念不理解,就是眉毛胡子一把抓,弄不出头绪。redux的概念,通过一张图大家就一目了然了。
这张图大致可以概括redux的整个流程。从图中我们可以看出,Action是数据流动的开始,Reducer负责业务逻辑处理,store是整个流程的中轴。
1、你从哪里来?——谈谈actions的起源
redux里的action和flux里的action大体上一致,不同的是设计理念的差别。flux里的action是以函数的形式,但在redux里,action被设计成普通的js对象。
{
type: 'ADD_TODO',
text: 'Build my first Redux app'
}
这就是一个最基本的action,必须注意的是,type是action必须的一个key值,是action的唯一标识。其它的key可以使任意像传递的数据结构。
但是actions到底代表什么?
actions代表着数据来源的萃取。我们的view界面需要很多数据结构,如ajax返回的数据、路由状态跟踪、UI状态等。。。关键的是这些数据都是动态流动的,既然流动,就要有入口、有方向。actions就是代表数据流动的开始,携带的key值中,type代表发生了什么事情,其它的就是需要流动的数据结构。
归纳起来,actions是数据从应用传到store的有效载荷,是store唯一的数据来源。
那么如何产生一个action,这就是又有一个概念actionCreator:
function addTodo(text) {
return { type: ADD_TODO,text };
}
actionCreator实际上是一个返回action值的函数而已。这样,只需把 action 生成器的结果传给 dispatch() 方法即可实例化 dispatch。
dispatch(addTodo(text));
2、条条大路通哪里?——看看reducer的神奇
action表示发生了什么事情,表明了有事情发生,肯定会对应用的数据产生影响。我们知道,React组件内的数据都是以state的形式存在的,state代表着数据结构。那么就要问了,action的发生到底会对state产生什么影响。这就是reducer的作用了。
reducer 其实是一个函数, 接收旧的 state 和 action, 返回新的 state。
(prevIoUsState,action) => newState
这种设计来源于函数式编程思想,简单,易懂,没有副作用。
function todoApp(state = initialState,action) {
switch (action.type) {
case SET_VISIBILITY_FILTER:
return Object.assign({},state,{ visibilityFilter: action.filter });
default:
return state;
}
}
可以看出,业务逻辑部分都是在reducer里处理。这就涉及一个问题,一个应用里有很多逻辑部分,都放在一个reducer里面会造成非常的臃肿。实际过程中,把业务进行分拆,然后通过combineReducer函数合并成一个reducer。详细可以看这里:
https://github.com/rackt/redux/blob/mast...
切记,在reducer不要改变旧的state值。
3、看看你是谁?——揭开store的面纱
首先我们看文档里怎么描述的:
The Store is the object that brings themtogether.(them指的是action和reducer)
It’s important to note that you’ll only have a single store in a Redux application.
这就说明,Store负责把reducer和action结合的作用。store怎么创建?一般是通过下面的代码:
const store = createStore(reducer);
这个createStore又是什么函数,我们看看createStore.js源码:
import isPlainObject from './utils/isPlainObject'; export var ActionTypes = { INIT: '@@redux/INIT' }; export default function createStore(reducer,initialState) { if (typeof reducer !== 'function') { throw new Error('Expected the reducer to be a function.'); } var currentReducer = reducer; var currentState = initialState; var listeners = []; var isDispatching = false; function getState() { return currentState; } function subscribe(listener) { listeners.push(listener); return function unsubscribe() { var index = listeners.indexOf(listener); listeners.splice(index,1); }; } function dispatch(action) { if (!isPlainObject(action)) { throw new Error( 'Actions must be plain objects. ' + 'Use custom middleware for async actions.' ); } if (typeof action.type === 'undefined') { throw new Error( 'Actions may not have an undefined "type" property. ' + 'Have you misspelled a constant?' ); } if (isDispatching) { throw new Error('Reducers may not dispatch actions.'); } try { isDispatching = true; currentState = currentReducer(currentState,action); } finally { isDispatching = false; } listeners.slice().forEach(listener => listener()); return action; } function replaceReducer(nextReducer) { currentReducer = nextReducer; dispatch({ type: ActionTypes.INIT }); } dispatch({ type: ActionTypes.INIT }); return { dispatch,subscribe,getState,replaceReducer }; }
我们可以看到createStore返回的是一个对象,该对象有四种方法,分别是:
dispatch,replaceReducer
可以看出redux里的store有点像flux里的dispatcher的作用,产生action可以通过store.dispatch发送出去,想监听状态可以通过store.subscribe订阅。
值得注意的是,程序初始化的时候,redux会发送一个类型为@@redux/INIT的action,来初始化state。
以上就是我对redux流程前半部分的理解,请批评指正。