分析redux源码

入口:index.ts(目录)重点标红

 

 

import createStore from './createStore'
import combineReducers from './combineReducers'
import bindActionCreators from './bindActionCreators'
import applyMiddleware from './applyMiddleware'
import compose from './compose'
import warning from './utils/warning'
import __DO_NOT_USE__ActionTypes from './utils/actionTypes'
// types// store
export {CombinedState, PreloadedState, Dispatch, Unsubscribe,  Observable, Observer, Store, StoreCreator, StoreEnhancer, StoreEnhancerStoreCreator,ExtendState} from './types/store'
// reducers
export {Reducer,ReducerFromReducersMapObject,ReducersMapObject,StateFromReducersMapObject,ActionFromReducer,ActionFromReducersMapObject} from './types/reducers'
// action creators
export { ActionCreator, ActionCreatorsMapObject } from './types/actions'
// middleware
export { MiddlewareAPI, Middleware } from './types/middleware'
// actions
export { Action, AnyAction } from './types/actions'

export {
  createStore,combineReducers,bindActionCreators,applyMiddleware,compose,__DO_NOT_USE__ActionTypes
}

 


用法: const store = createStore( rootReducer, applyMiddleware(thunk));  
createStore接收3个参数(reducer,preloadedState?,enhancer); 上面的applyMiddleware(trunk) 即 enhancer,
如果没有传preloadState参数则会这样:
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') { 
      enhancer = preloadedState as StoreEnhancer<Ext, StateExt> 
      preloadedState = undefined 
    }
没有enhancer的情况下,createStore会dispatch一个内部定义的action 来 初始化state,然后返回store
dispatch({ type: ActionTypes.INIT } as A)

  const store = ({
    dispatch: dispatch as Dispatch<A>,
    subscribe,
    getState,
    replaceReducer,
    [$$observable]: observable
  } as unknown) as Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext
  return store

 

而有enhancer参数传入的情况下, enhancer被调用两次之后,也同样返回了store
 if (typeof enhancer !== 'undefined') {
    if (typeof enhancer !== 'function') {
      throw new Error('Expected the enhancer to be a function.')
    }
  
//两次调用
return enhancer(createStore)(reducer,preloadedState as PreloadedState<S>) as Store<ExtendState<S, StateExt>, A, StateExt, Ext> & Ext}

 redux 设置了锁,来避免出现一些同步执行一些方法会导致的问题,如果一些情况同步执行,会报错,比如说同时更改和写入state的情况。

let isDispatching = false  //加锁
//初始化state
let currentState = preloadedState as S //preloadState是参数
//获取state的函数:
 function getState(): S {
if (isDispatching) { throw new Error( 'You may not call store.getState() while the reducer is executing. ' + 'The reducer has already received the state as an argument. ' + 'Pass it down from the top reducer instead of reading it from the store.' ) } return currentState as S }

 

let currentListeners: (() => void)[] | null = [] //初始化当前订阅者列表

let nextListeners = currentListeners //新订阅者列表

 

 sunscribe方法:接受一个listener作为参数,产生一个新的listener列表,把新的Listener加入新列表里面,返回unsubscribe方法。
(我们会调用dispatch函数来更新state,而每次state更新时,会通知每个listener。)

function subscribe(listener: () => void) { if (typeof listener !== 'function') { throw new Error('Expected the listener to be a function.') }   //锁 if (isDispatching) { throw new Error( 'You may not call store.subscribe() while the reducer is executing. ' + 'If you would like to be notified after the store has been updated, subscribe from a ' + 'component and invoke store.getState() in the callback to access the latest state. ' + 'See https://redux.js.org/api-reference/store#subscribelistener for more details.' ) } let isSubscribed = true ensureCanMutateNextListeners() nextListeners.push(listener)   
   function ensureCanMutateNextListeners() {
    //判断是否指向同一个对象
      if (nextListeners === currentListeners) {
        nextListeners = currentListeners.slice()
      }
    }
return function unsubscribe() {
      if (!isSubscribed) {
        return
      }
    if (isDispatching) {
        throw new Error(
          'You may not unsubscribe from a store listener while the reducer is executing. ' +
            'See https://redux.js.org/api-reference/store#subscribelistener for more details.'
        )
      }
    
      isSubscribed = false //设置已经退订
     ensureCanMutateNextListeners() //复制到新的订阅者列表
      const index = nextListeners.indexOf(listener) 
      nextListeners.splice(index, 1) //删除该订阅者
      currentListeners = null
    }
  }

 

dispatch函数   (参数是action),调用reducer函数 更新state,并且通知所有最新的listener

let currentReducer = reducer //第一个参数reducer 
function dispatch(action: A) { 
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
    //执行传入参数的reducer,返回新的state
currentState = currentReducer(currentState, action) } finally { isDispatching = false }    //更新Listener列表,通知所有listener const listeners = (currentListeners = nextListeners) for (let i = 0; i < listeners.length; i++) { const listener = listeners[i] listener() } return action }

 其他:

replaceReducer //替换reducer

observable // observable版本的实现

 

2,applyMiddleware.ts

//记得createStore的参数enhancer吗?applyMiddleware(thunk)的返回值,一个函数,被执行了2次。
最终它返回了store,并且加了一个dispatch属性在上面(这个dispatch方法是经过包装过的,最里面才是原来的store.dispatch方法)

//定义参数部分略

export default function applyMiddleware( ...middlewares: Middleware[] ): StoreEnhancer<any> { return (createStore: StoreCreator) => <S, A extends AnyAction>( reducer: Reducer<S, A>, ...args: any[] //state ) => {
   //初始化store,这里store会有一个dispatch的方法,这个dispatch会被传给middleware,经过一系列包装。
    const store = createStore(reducer, ...args)
  //变量dispatch
let dispatch: Dispatch
= () => { throw new Error( 'Dispatching while constructing your middleware is not allowed. ' + 'Other middleware would not be applied to this dispatch.' ) } const middlewareAPI: MiddlewareAPI = { getState: store.getState, dispatch: (action, ...args) => dispatch(action, ...args)//把变量dispatch也传给了middlewares }
  //执行了一次middlewares,传递参数。 const chain
= middlewares.map(middleware => middleware(middlewareAPI))

  
//调用了compose2次,且最终返回新的dispatch方法,赋值给变量dispatch。   dispatch = compose<typeof dispatch>(...chain)(store.dispatch)   //设定新的store.dispatch 并返回 store return { ...store, dispatch } } }
compose.ts
//参数定义略
export default function compose(...funcs: Function[]) { if (funcs.length === 0) { // infer the argument type so it is usable in inference down the line return <T>(arg: T) => arg //T是dispatch函数,dispatch = store.dispatch } if (funcs.length === 1) { return funcs[0] //只有一个,直接返回,然后被传入store.dispatch }  //如果多个参数,多个dispatch合一(嵌套)
  return funcs.reduce((a, b) => (...args: any) => a(b(...args))) 
}

 so.. middlewares

redux-trunk源码:
function createThunkMiddleware(extraArgument) {return 
  //trunk函数
({ dispatch, getState }) =>
    //被传入middlewareAPI之后
    next =>
    //被传入store.dispatch之后,dipatch = action=>{return dispatch(action)}
       action => {
         if (typeof action === 'function') {
            return action(dispatch, getState, extraArgument);
             }
         return next(action);
  };
}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;

export default thunk;
用法: dispatch(actionCreater(params))
export function actionCreater(params){
//返回的dispatch函数
return (dispatch,getState)=>{ sendAsyncRequest(params).then((response)=>{ let action ={ type:'WHAT_EVER', payload:response }; return dispatch(action); }) } }


 

 3.combineReducer.ts

 

用法:  const rootReducer = combineReducers({
    theDefaultReducer,
    firstNamedReducer,
    secondNamedReducer
  });

作用,把reducers合成同一个

//定义类型略
//错误处理代码略
export default function combineReducers(reducers: ReducersMapObject) {
  //获取key const reducerKeys
= Object.keys(reducers) const finalReducers: ReducersMapObject = {} for (let i = 0; i < reducerKeys.length; i++) { const key = reducerKeys[i] if (process.env.NODE_ENV !== 'production') { if (typeof reducers[key] === 'undefined') { warning(`No reducer provided for key "${key}"`) } } if (typeof reducers[key] === 'function') {
    //设定value finalReducers[key] =
reducers[key] } } const finalReducerKeys = Object.keys(finalReducers) // This is used to make sure we don't warn about the same // keys multiple times. let unexpectedKeyCache: { [key: string]: true } if (process.env.NODE_ENV !== 'production') { unexpectedKeyCache = {} } let shapeAssertionError: Error try { assertReducerShape(finalReducers) } catch (e) { shapeAssertionError = e }   //返回的combinedreducer return function combination( state: StateFromReducersMapObject<typeof reducers> = {}, action: AnyAction ) { if (shapeAssertionError) { throw shapeAssertionError } if (process.env.NODE_ENV !== 'production') { const warningMessage = getUnexpectedStateShapeWarningMessage( state, finalReducers, action, unexpectedKeyCache ) if (warningMessage) { warning(warningMessage) } } let hasChanged = false const nextState: StateFromReducersMapObject<typeof reducers> = {}
  //遍历来比较
for (let i = 0; i < finalReducerKeys.length; i++) { const key = finalReducerKeys[i] const reducer = finalReducers[key] const previousStateForKey = state[key]
  //获取新的state const nextStateForKey
= reducer(previousStateForKey, action) if (typeof nextStateForKey === 'undefined') { const errorMessage = getUndefinedStateErrorMessage(key, action) throw new Error(errorMessage) } nextState[key] = nextStateForKey
  //判断state的值有没有改变 hasChanged
= hasChanged || nextStateForKey !== previousStateForKey }
  //判断key有没有改变 hasChanged
= hasChanged || finalReducerKeys.length !== Object.keys(state).length
  //如果有改变返回新state
return hasChanged ? nextState : state } }

 bindActionCreators .ts

文档: 惟一会使用到 bindActionCreators 的场景是当你需要把 action creator 往下传到一个组件上,却不想让这个组件觉察到 Redux 的存在,而且不希望把 dispatch或 Redux store 传给它。

把一个 value 为不同 action creator 的对象,转成拥有同名 key 的对象。同时使用 dispatch 对每个 action creator 进行包装,以便可以直接调用它们。

一般情况下你可以直接在 Store 实例上调用 dispatch。如果你在 React 中使用 Redux,react-redux 会提供 dispatch 函数让你直接调用它 。

export default function bindActionCreators(
  actionCreators: ActionCreator<any> | ActionCreatorsMapObject,
  dispatch: Dispatch
) {
  //function type
if (typeof actionCreators === 'function') { return bindActionCreator(actionCreators, dispatch) }    if (typeof actionCreators !== 'object' || actionCreators === null) { throw new Error( `bindActionCreators expected an object or a function, instead received ${ actionCreators === null ? 'null' : typeof actionCreators }. ` + `Did you write "import ActionCreators from" instead of "import * as ActionCreators from"?` ) }  //默认,如果是包含function的{} const boundActionCreators: ActionCreatorsMapObject = {} for (const key in actionCreators) { const actionCreator = actionCreators[key] if (typeof actionCreator === 'function') { boundActionCreators[key] = bindActionCreator(actionCreator, dispatch) } } return boundActionCreators }

  function bindActionCreator<A extends AnyAction = AnyAction>( actionCreator: ActionCreator<A>, dispatch: Dispatch ) {
    return function(this: any, ...args: any[]) {
      return dispatch(actionCreator.apply(this, args))
  }
}
 

 

 

posted @ 2020-03-09 06:43  Esther_Cheung  阅读(380)  评论(0)    收藏  举报