Redux是一个用于状态管理的js框架,是Flux架构的一种实现(如图)。
Redux核心概念
- store
是一个对象,所有状态集中存储的地方,并全局唯一,称为状态树。并包含以下几个操作方法:getState()
获取当前的状态树;dispatch(action)
分发一个动作,以改变状态树中对应的状态;subscribe(listener)
添加一个监听器,以监听状态树的变化,当状态树变化时,会马上执行传入的函数。会返回一个unsubscribe函数,执行该函数可以解绑该监听器。replaceReducer(nextReducer)
用于热加载,暂时不重要。
- reducer
为一个用户自定义的函数,在store分发(dispacth)action时提供处理方法去更新状态树中的状态。应该为一个纯函数。 - action
为一个用户自定义的对象,里面包含一个type属性,标识一个动作类型。
核心概念总结:store是存储所有状态的地方,改变状态的唯一方法就是通过调用store的dispatch方法分发相应的动作,该动作会经过每个用户定义的reducer,reducer通过识别action的type,以及接收原来的状态返回一个新的状态。
redux核心api
createStore(reducer, initState)
根据用户定义的reducer创建一个store。第二个参数为初始状态,可选;combineReducers(reducers)
把用户定义的多个reducer合并为一个。
逐步代码实现(涉及ES6语法):
createStore
1、createStore函数的大概样子:
const createStore = (reducer, initState)=>{
const state = initState || {}; //初始状态;
return { //store的核心操作方法;
getState(){
return state;
}
dispatch(action){}
subscribe(){}
};
}
2、dispatch(action)
方法实现:
dispatch方法是比较复杂的一个方法,应做的工作有:检测action,检测及防止dispatch死循环,触发监听器。
const createStore = (reducer, initState)=>{
let state = initState || {}; //初始状态;
/* 新增代码 */
let inDispatch = false; //是否正在分发action
const listeners = []; //监听器
/* *********** */
return { //store的核心操作方法;
getState(){
return state;
}
dispatch(action){
/* 新增代码 */
//1、检测action合法性
if(!action || typeof action !== 'object' || !action.type){
throw new Error('action invalid');
}
//2、检测是否正在分发,以防止在reducer中调用dispatch而导致死循环。
if(inDispatch){
throw new Error('can not dispatch a action now!');
}
//3、分发action
try{
inDispatch = true;
state = reducer(state, action);
}finally{
inDispatch = false;
}
//4、触发所有监听器
listeners.forEach(listener => listener());
/* *********** */
}
subscribe(){}
};
}
3、subscribe(listener)
方法实现:
subscribe方法除了添加监听器之外,还应检测重复监听,返回一个解绑函数。
const createStore = (reducer, initState)=>{
let state = initState || {}; //初始状态;
let inDispatch = false; //是否正在分发action
const listeners = []; //监听器
return { //store的核心操作方法;
getState(){
return state;
}
dispatch(action){
//1、检测action合法性
if(!action || typeof action !== 'object' || !action.type){
throw new Error('action invalid');
}
//2、检测是否正在分发,以防止在reducer中调用dispatch而导致死循环。
if(inDispatch){
throw new Error('can not dispatch a action now!');
}
//3、分发action
try{
inDispatch = true;
state = reducer(state, action);
}finally{
inDispatch = false;
}
//4、触发所有监听器
listeners.forEach(listener => listener());
}
subscribe(listener){
/* 新增代码 */
if(listeners.some(item => item===listener))return; //检测重复监听
const pos = listeners.push(listener) - 1; //记录该监听器的位置
return ()=>{
//返回函数为删除该位置的监听器
if(listeners[pos] === listener){
listeners.splice(pos,1);
}
};
/* *********** */
}
};
}
这样,Redux的核心功能就实现了。
combineReducers
实现combineReducers 应该考虑到多层、多个reducer的情况,并且能自动将action逐层分发至每个子reducer。
1、combineReducers大概的样子:
const combineReducers = (reducers){
if(!reducers || typeof reducers !== 'object'){
throw new Error('invalid reducers.');
}
return (action)=>{};
}
2、关键代码实现:
const combineReducers = (reducers){
if(!reducers || typeof reducers !== 'object'){
throw new Error('invalid reducers.');
}
return (state, action)=>{
/* 新增代码 */
const newState = {};
for(key in reducers){
newState[key] = reducers[key](state[key], action);
}
return newState;
/* *********** */
};
}