redux源码解析

redux导出一个对象,对象拥有createStore,bindActionCreators,combineReducers,applyMiddleware这几个核心的key。

import createStore from './createStore.js';
import bindActionCreators from './bindActionCreators.js';
import combineReducers from './combineReducers.js';
import applyMiddleware from './applyMiddleware.js';
export {
  createStore,
  bindActionCreators,
  combineReducers,
  applyMiddleware
}

1.createStore
是创建一个仓库,导出一个对象,对象拥有getState,dispatch,subscribe这三个key。。getState是用来获取state值,dispatch是用来派发执行reducers,subscribe是用来订阅。
工具函数用来判断是否是纯对象

function isPlainObject(obj){
		if(typeof obj!=='object' || obj===null){
			return false;
	}
		let proto =obj;
		while(Object.getPrototypeOf(proto)){
			proto=Object.getPrototypeOf(proto);
		}
	return Object.getPrototypeOf(obj)===proto;
}

reducer 函数必须是一个函数,它相当于处理器。用来合并修改state状态值。
action是一个对象,相当于动作行为。dispatch派发动作执行相应的reducer 处理器。createStore内部还实现了一个发布订阅的模式,订阅方:subscribe函数,发布方:在dispatch内部执行所收集的currentListeners数组。

import isPlainObject from '../utils/isPlainObject.js';
import ActionTypes from '../utils/actionTypes.js';
//reducer 是一个纯函数 preloadedState 是初始状态
export default function createStore(reducer,preloadedState){
  if(typeof reducer !=='function'){
    throw new Error('reducer必须是一个函数');
  }
  let currentState=preloadedState;//当前状态
  let currentReducer=reducer;//当前处理器
  let currentListeners=[];//定义一数组保存当前的监听函数
  
  //用来获取状态值
  function getState(){
    return currentState;
  }
  //action {type:'xxx'};action是一个纯对象,必须拥有type属性
  function dispatch(action){
    if(!isPlainObject(action)){
      throw new Error('action必须是一个纯函数');
    }
    if(typeof action.type==='undefined'){
      throw new Error('action的type属性不能是undefined');
    };
    //将 初始的状态和action对象传递给reducer处理器
    currentState=currentReducer(currentState,action);
    //发布
    for(let i=0;i<currentListeners.length;i++){
      const listener=currentListeners[i];
      listener();
    }
    return action;
  }
  //订阅函数
  function subscribe(listener){
    let subscribe=true;		//开关用来优化数组
    currentListeners.push(listener);
    return function unsubscribe(){
      if(!subscribed) return ;
      const index=currentListeners.indexOf(listener);
      currentListeners.splice(index,1);
      subscribe=false;
    }
  }
   //默认先执行一次dispatch函数,是为了将初始状态传递给reducer
   dispatch({type:ActionTypes.INIT});
  return {
    getState,
    dispatch,
    subscribe
  }
}

2、bindActionCreators
是用来将定义的action动作对象自动绑定到dispatch上进行派发。不需要手动去执行dispatch函数。

//此函数将原action函数进行重写
/*
action  return { type:'xxx}
        return dispatch( {type:'xxx'})
*/
//重写action函数
function bindActionCreator(actionCreator,dispatch){
  return function(){
    return dispatch(actionCreator.apply(this,arguments))
  };
}
//返回一个已经将action的行为绑定在dispatch上的对象
export default function bindActionCreators(actionCreators,dispatch){
  if(typeof actionCreator==='function'){
    return bindActionCreator(actionCreators,dispatch);
  }
  const boundActionCreators={};
  for(const key in actionCreators){
    boundActionCreators[key]=bindActionCreator(actionCreators[key],dispatch);
  }
  return boundActionCreators;
}

3、combineReducers
是用来合并reducer,不同模块处理器可能不一样,为了只创建一个公共的仓库,即一个state状态。将不同模块的reducer处理器进行合并,返回合并后的state。

/*
将reducer进行合并,就是重写自己写的reducer处理器的过程返回合并后的state
*/
export default function(reducers){
  const reducerKeys=Object.keys(reducers);
  return function(state={},action){
    const nextState={};
    for(let i=0;i<reducerKeys.length;i++){
      const key=reducerKeys[i];
      const reducer=reducers[key];
      const previousStateForKey=state[key];
      //执行单个reducer,将初始状态传入。
      const nextStateForKey=reducer(previousStateForKey,action);
      nextState[key]=nextStateForKey;
    }
    return nextState;
  }
}

4、applyMiddleware
是用来处理中间件的函数。其实就是将中间件进行合并处理,并且重写了createStore的dispatch函数。
工具函数:是用来合并函数,中间件的合并是由里到外。

function compose(...funcs){
 return funcs.reduce((a,b)=>(...args)=>a(b(...args)))
}
//还可以有以下几种写法
function compose1(...funcs){
  return function(...arg){
    let result;
    for(let i=funcs.length-1;i>=0;i--){
      result=funcs[i](i==funcs.length-1?arg:result);
    }
    return result;
  }
}
function compose3(...funcs){
     return funcs.reduce((a,b)=>{
      return (...args)=>{
          return a(b(...args));
      };
    })
}
function compose4(...fns){
  let args=arguments;
  let start =args.length-1;
  return function(){
    let i=start;
    let result =args[start].apply(this,arguments);
    while(i--){
      result=args[i].call(this,result);
    }
    return result;
  }
}
import compose from './compose.js';
export default function applyMiddleware(...middlewares){  //middlewares=[logger1,logger2]
  return function(createStore){
    return function(reducer){
      let store=createStore(reducer);   //最开始的原生仓库
      let dispatch=()=>{
        throw Error('现在还不能用!');
      }
      let middlewareAPI={
        getState:store.getState,
        dispatch:(...args)=>{dispatch(...args)}
      };
       //chain =[logger1下第二层,logger2第二层]
      const chain=middlewares.map(middleware=>middleware(middlewareAPI));
      dispatch=compose(...chain)(store.dispatch);
      return {
        ...store,
        dispatch
      }
    }
  }
}

thunk的源码解析
thunk还可以接收一个额外的参数,中间件的处理是由外到里。

function createThunkMiddleware(extraArgumrnt){
  return ({dispatch,getState})=>next=>action=>{
    if(typeof action === 'function'){
      return action(dispatch,getState,extraArgumrnt)
    }else{
      next(action);
    }
  }
}
const thunk=createThunkMiddleware();
thunk.withExtraArgument=createThunkMiddleware;
export default thunk;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值