一:为什么需要redux
随着JavaScript
单页应用开发日趋复杂,管理不断变化的state
变得十分困难。状态的变更也变的十分难以追踪,这时候一种新的管理方式需要被使用,所以redux
产生了。
二:三大原则
-
【一】单一数据流
整个应用的
state
被储存在一棵object tree
中,并且这个object tree
只存在于唯一的store
中。单一数据流使得我们的管理变得更简单 -
【二】只读
state
唯一改变
state
的方法就是触发action
。唯一的改变方法可以防止数据被任意更改,变得难以追踪。 -
【三】使用
reducer
函数执行修改 根据触发的
action
来通知reducer
函数来执行相应修改state
动作。
三:设计思想
-
【一】将整个应用状态存储到到一个地方,称为
store
,里面保存一棵状态树state tree
-
【二】组件可以派发
dispatch
行为action
给store
,而不是直接通知其它组件 -
【三】其它组件可以通过订阅
store
中的state
来刷新自己的视图
更详细的流程
四:最基本使用
-
创建存储仓库
store
import {createStore} from 'redux'; let initState = {}; let store = createStore(reducer,initState); // 有两个参数
-
定义
action
动作,表示怎么更改我们的state
const INCREMENT = 'INCREMENT'; const DECREMENT = 'DECREMENT';
-
创建
reducer
,实际的去更改我们的state
function reducer(state, action) { // 传入原始state和我们的action对象,action一般包含type和patload switch (action.type) { case INCREMENT: return state + 1; // 返回一个加1的新状态 case DECREMENT: return state - 1;// 返回一个减1的新状态 default: return state; } }
-
调用
dispatch
去更改我们的状态,例如有一个增加按钮和一个减少按钮<button onClick = {this.increase}>增加</button> <button onClick = {this.decrease}>减少</button> // 增加 function increase() { // 派发一个dispatch store.dispatch({ type:INCREMENT }) } // 减少 function decrease() { store.dispatch({ type:DECREMENT }) }
五:Redux中间件
引入:在开发的过程中往往我们需要在dispatch
之前增加一些自己的代码逻辑,也就是需要我们使用中间件,在redux
的设计中就考虑到了这个事情,所以为我们提供了applyMiddleware
这个方法。相当于封装了一层我们的dispatch
,让功能更加丰富
中间件思想模拟(aop切片思想)
- 【1】保存原有的
dispatch
方法 - 【2】重写
store
中的dispatch
方法 - 【3】在重写的
dispatch
方法中插入自己的逻辑 - 【4】在重写的
dispatch
方法中执行保存的原有dispath
方法
例如:
/**
* store/index.js
*/
import { createStore } from 'redux';
import reducers from './reducers';
const store = createStore(reducers);
/*【1】保存原有的dispatch方法*/
const middleWare = store.dispatch;
/*【2】重写store中的dispatch方法*/
store.dispatch = function(action){
/*【3】在重写的`dispatch`方法中插入自己的逻辑*/
console.log('老状态',store.getState());
/*【4】在重写的`dispatch`方法中执行保存的原有`dispath`方法*/
middleWare(action);
/*【3】在重写的`dispatch`方法中插入自己的逻辑*/
console.log('新状态',store.getState());
}
export default store;
另外有关中间件的详细讲解请看我的另一篇文章:指引
六:React-redux
这里推荐去看阮老师的博客,已经十分详细了,指引
七:redux-action
当我们的action变得特别多的时候,我们可以使用这个npm包来进行action管理,具体请看官网。具体的坑之后再补。
八:关键函数讲解
-
createStore
主要参数:
reducer
,initState
(初始对象)主要返回:
getState
,subscribe
,dispatch
主要源码(自我实现):
function createStore(reducer,preloadedState){ let currentReducer = reducer; let currentState = preloadedState; let currentListeners = []; function getState(){ return currentState; } function dispatch(action){ if(!isPlainObject(action)){ throw new Error('action必须是一个纯对象'); } if(typeof action.type === 'undefined'){ throw new Error('action必须有type属性') } currentState = currentReducer(currentState,action); for(let i = 0;i<currentListeners.length;i++){ const listener = currentListeners[i]; currentListener(); } return action; } function subscribe(listener){ currentListeners.push(listener); return function(){ const index = currentListeners.indexOf(listener); currentListeners.splice(index,1); } } return { getState, dispatch, subscribe } }
-
combineReducers
参数:
reducers
对象返回:
reducers
函数主要源码(自我实现):
function combineReducers(reducers){ const reducerKeys = Object.keys(reducers); return function(state={},action){ const nextState = {}; for(let i = 0;i<reducerKeys.length;i++){ //遍历所有的reducer const reducer = reducers[key]; // 拿到对应的reducer的值 const previousStateForkey = state[key]; // 拿到原始状态 const nextStateForkey = reducer(previousStateForkey,action); // 求出新状态 nextState[key] = nextStateForkey; // 更新state } return nextState; // 返回state } }