Redux+ReactRedux源码解析

export const ActionTypes = {INIT:'@@redux/INIT'}

// 生成一个store,和维护这个store需要的方法

// 维护一个state,暴露dispatch(action)来驱动调用传入的reducer(oldstate,action)得到修改后的state

// 维护一个listener队列,在调用reducer(oldstate,action)后遍历调用

// 预留一个接口增强dispatch的功能(添加中间件)

// 参数:

// reducer  接受action返回next state tree的一个function

// preloadedState store生成时的初始state

  // 如果通过combineReducers生成了根reducer函数,此时必须使用combineReducers相同的key

// enhancer applyMiddleware 中间件,多个中间件通过appleMiddleware()来组合

// 返回:一个Redux stroe (读取state,发送action,监听state改变)

export default function createStroe(reducer,preloadedState,enhancer){

    // 入参第二参数类型是否为函数,第三个参数未定义

    if(typeof preloadedState === 'function' && typeof enhancer == 'undefined'){

    // 根据参数类型,判断第二参数传入的是enhancer,此时将传入的值做调整

        enhancer = preloadedState;

        preloadedState = undefined;   

    }


    if(typeof enhancer !== 'undefined'){

        if(typeof enhancer !== 'function'){

            throw new Error('enhancer to be a function')

        }

        // 传入了三个参数,并且第三个参数is a function(中间件),此时执行科里化

        // 先执行中间件,在调用createStore

        return enhancer(createStroe)(reducer,preloadedState);

    }

    // 判断第一个参数是否是function

    if(typeof reducer !== 'function'){

        throw new Error('reducer to be a function');

    }

    // 参数校验成功,传入了两个参数,且参数类型也合规

    let currentReducer  = reducer

    // 初始state

    let currentState = preloadedState

    // 构造监听队列

    let currentListeners = []

    let nextListeners = currentListeners

    let isDispatching = false

    function ensureCanMutateNextListeners(){

        if(nextListeners == currentListeners){

            // 浅拷贝监听数据

            nextListeners = currentListeners.slice();

        }

    }

    // 通过Store去读state树

    function getState(){

        return currentState

    }

    // 添加订阅监听

    // 传入监听回调

    // 返回一个移除监听的方法)

    function subscribe(listener){

        if(typeof listener !== 'function'){

            throw new Error('listent to be a function')

        }

        let isSubscribed = true;

        // 监听前后队列传递

        ensureCanMutateNextListeners();

        // 添加监听

        nextListeners.push(listener)

        return function unsubscribe(){

            // 是否正在添加监听 同步锁

            if(!isSubscribed){

                return;

            }

            isSubscribed = false;

            // 监听前后队列传递

            ensureCanMutateNextListeners();

            // 判断监听是否已经添加到将监听的队列中

            const index = nextListeners.indexOf(listener);

            // 已添加的要移除

            nextListeners.splice(index,1);

        }


    }

    //发送一个Action,驱动state的改变

    // 参数:action,要操作的行为

    // 返回:传入的action

    function dispatch(action){

        // 判断传入的action是否唯一个原生对象,而不是a Promise, an Observable, a thunk, or something else,

        if(!isPlainObject(action)){

            throw new Error(

                'Actions must be plain objects'+

                'Use custom middleware for async actions'

            );

        }

        // 判断传入的action是否有type

        if(typeof action.type === 'undefined'){

            throw new Error(

                'Actions may not have an undefined "type" property.'

            );

        }

        // 判断正在执行(同步锁)

        if(isDispatching){

            throw new Error('reducers may not dispatch actions');

        }

        // 将当前state,和传入的action作为参数,调用reducer获取修改后的state

        try{

            isDispatching = true;

            currentState = currentReducer(currentState,action)

        }finally{

            isDispatching = false

        }

        // 处理监听

        // 传递nextListeners 到currentListeners,然后执行这些监听回调

        const listeners = currentListeners = nextListeners;

        for(let i = 0;i

            const listener = listeners[i];

            listener();

        }

        return action;

    }

    function replaceReducer(nextReducer){

        if(typeof nextReducer !== 'function'){

            throw new Error('Expected reducer to be a function')

        }

        currentReducer = nextReducer

        dispatch({type:ActionTypes.INIT});

    }

// 为observable/reactive库预留的交互接口。

    function observable(){


        const outerSubscribe = subscribe;


        return{

            subscribe(observer){

                if(typeof observer != 'object'){

                    throw new TypeError('Expected the observer to be an object')

                }

                function observeState(){

                    if(observer.next){

                        observer.next(getState())

                    }

                }

                observeState();

                const unsubscribe = outerSubscribe(observeState);

                return {unsubscribe}

            },

            [$$observable](){

                return this

            }

        }

    }

    // 调用createStore时,dispatch return initial state

    dispatch({type: ActionTypes.INIT})

    return{

        dispatch,

        subscribe,

        getState,

        replaceReducer,

        [$$observable]: observable

    }

}

// conbineReducers.js reducer组合工具类

// 将一个包含了不同的reducer函数的对象,转换成一个集合reducer函数

// 在集合reducer函数中调用每一个子reducer,将他们的结果,聚集到一个state对象中,所用的key要跟redecer

// 参数 对象(包含多个reducer属性)

// 返回了一个方法,遍历执行所有属性reducer,将每个reducer返回的state,拼装成一个state树

// 所以每次dispatch调用的render时调用的就是combination()

exprot default function combineReducers(reducers){

    // 获取传入对象的key集合

    const reducerKeys = Object.keys(reducers);

    const finalReducers = {};

    for(let i = 0;i

        const key = reducerKeys[i];

        // 校验传入的对象属性都有值

        if(process.env.NODE_ENV !== 'production' ){

            if(typeof reducers[key] === 'undefined'){

            }

        }

        //

        if(typeof reducers[key] === 'function'){

            finalReducers[key] = reducers[key]

        }

    }

    // 浅拷贝出有效的reducer属性

    const finalReducerKeys = Object.keys(finalReducers);

    let unexpectedKeyCache

    if(process.env.NODE_ENV !== 'production'){

        unexpectedKeyCache = {}

    }

    let shapeAssertingError

    try{

        // 调用finalReducers中每一个reducer的Init事件

        assertReducerShape(finalReducers)

    }catch(e){

        shapeAssertingError = e;

    }

    return function combination(state = {},action){

        if(shapeAssertingError)

        {

            throw shapeAssertingError;

        }

        if(process.env.NODE_ENV !== 'production'){

            const warningMessage = getUNexpectedStateShapeWarningMessage(state,finalReducers,action,unexpectedKeyCache)

            if(warningMessage){

            }

        }

        let hasChanged = false;

        const nextState = {}

        // 遍历finalReducers,构建一个state树,以finalReducers中reducer的key为key,reduer执行生成的state为value

        for(let i = 0;i

            // 获取reducer的key

            const key = finalReducerKeys[i];

            // 获取reducer的value

            const reducer = finalReducers[key];

            // 从state树上根据reducer的key获取之前的state值

            const previousStateForKey = state[key]

            // 根据执行reducer的value得到新的state值

            const nextStateForkey = reducer(previousStateForKey,action);


            if(typeof nextStateForkey === 'undefined'){

                throw new Error();

            }

            // 将得到新的state值,update到state树

            nextState[key] = nextStateForkey;

            hasChanged = hasChanged || nextStateForkey !== previousStateForKey


        }

        return hasChanged?nextState:state

    }

}

// 中间件集合类

// applyMiddleware,将接受到的middleware参数装换成middleware数组

// 再转换成一个初始参数为原始dispatch的一元链式函数 dispatch = w1(w2(w3(store.dispatch)))

// 从而生成新的加强了的dispatch方法

export default function applyMiddleware(...middleware){

    return(createStroe)=>(reducer,preloadedState,enhancer)=>{


        const store = createStroe(reducer,preloadedState,enhancer)

        let dispatch = store.dispatch

        let chain = []

        const middlewareAPI = {

            getState:store.getState,

            dispatch:(action) => dispatch(action)

        }

        chain = middlewares.map(middleware => middleware(middlewareAPI))


        dispatch = compose(...chain)(store.dispatch)


//      dispatch = w1(w2(w3(store.dispatch)))

        return {

            ...store,

            dispatch

        }

    }

}

// 将第一个函数调用结果做为下一个函数的参数

export default function compose(...funcs){

    if(funcs.length === 0){

        return arg => arg

    }

    if(funcs.length === 1){

        return funcs[0]

    }

    return funcs.reduce(((a,b)=>(...args) => a(b(...args)))

}

// action生成器 bindActionCreator

function bindActionCreator(actionCreator,dispatch){

    return (...args) => dispatch(actionCreator(...args))

}

// bindActionCreators

// 将一个所有属性都是action creators的对象,转换成

// 参数:

export default function bindActionCreators(actionCreators,dispatch){

    const keys = Object.keys(actionCreators)

    const boundActionsCreators = {}

    for (let i = 0;i

        const key = keys[i];

        const actionCreator = actionCreators[key]

        if(typeof actionCreator === 'function'){

            boundActionsCreators[key] = bindActionCreator(actionCreator,dispatch);

        }

    }

    return boundActionsCreators

}

// React-Redux  redux 在react上应用的辅助工具类

// 生成一个控件,使其将createStore生成state作为store ,利用React中的Context属性

// 对Provider 添加getChildContext和childContextTypes,

// 将store 传递到其所有子控件中,以供其访问

//

// Provider createProvider

//

//    Component

//

export function createProvider(storekey = 'store',subKey){

    const subscrptionKey = subKey || `${storeKey}Subscription`

    class Provider extends Component{

        getChildContext(){

            return {[storeKey]:this[storeKey],[subscrptionKey]:null}

        }

        constructor(props,context){

            super(props,context)

            this[storeKey] = props.store;

        }

        render(){

            return Children.only(this.props.children)

        }

    }

    Provider.prototype = {

        store:storeShape.isRequired,

        children:PropTypes.element.isRequired,

    }

    Provider.childContextTypes = {

        [storeKey]: storeShape.isRequired,

        [subscriptionKey]: subscriptionShape,

    }

    return Provider

}

//

// export default connect(mapStateToProps, mapDispatchToProps)(containerName)

// 将UI组件(只展现UI)转换成可以访问Redux API 的容器组件(处理业务逻辑,和管理数据)

// 通过Provider将createStore生成的state传递到其所有子控件后

exprot function createConnect({

//参数

    connectHOC = connectAdvanced,

    mapStateToPropsFactories

    ...

}={}){

// 函数体  返回一个函数

    return function connect(mapStateToProps,mapDispatchToProps,mergeProps

        // 第四个参数

        {

            pure = ture,

            ....

        }

    ){


        // 将传入的mapStateToProps作为实参,

        // 通过match遍历调用mapStateToPropsFactories(数组)中对应的方法(对传入

        // 的mapStateToProps做判断校验)


            // 如果 mapStateToProps 为null

                // wrapMapToPropsConstant(() => ({}))

            // 如果 mapStateToProps 为function

                // wrapMapToPropsFunc(mapStateToProps, 'mapStateToProps')

                // export function wrapMapToPropsFunc(mapToProps, methodName) {

                    //    返回一个方法

                //    return function initProxySelector(dispatch, { displayName }) {

                        // 返回一个方法 initProxySelector (initMapStateToProps)

                        // 声明一个方法 proxy

                //      const proxy = function mapToPropsProxy(stateOrDispatch, ownProps) {

                //          调用proxy 时

                //              dependsOnOwnProps 

                                    // 为true 执行 proxy.mapToProps(stateOrDispatch, ownProps)

                                    // 为false 执行 proxy.mapToProps(stateOrDispatch)

                //          return proxy.dependsOnOwnProps

                //          ? proxy.mapToProps(stateOrDispatch, ownProps)

                //          : proxy.mapToProps(stateOrDispatch)

                //      }

                //      给proxy添加属性 dependsOnOwnProps,标示是否有ownProps参数

                //      // allow detectFactoryAndVerify to get ownProps

                //      proxy.dependsOnOwnProps = true

                        // 给proxy添加属性mapToProps

                //      proxy.mapToProps = function detectFactoryAndVerify(stateOrDispatch, ownProps) {

                    //    第一次调用mapToProps时调用detectFactoryAndVerify,

                    //    此时拿到传入的MapStateToProps 指定给mapToProps

                            //

                //        proxy.mapToProps = mapToProps

                        //  判断传入的 mapToProps 的 dependsOnOwnProps属性是否为true

                //        proxy.dependsOnOwnProps = getDependsOnOwnProps(mapToProps)

                            //

                            // 再次调用proxy,调用的就是传入的 mapStateToProps

                //        let props = proxy(stateOrDispatch, ownProps)


                //        if (typeof props === 'function') {

                //          proxy.mapToProps = props

                //          proxy.dependsOnOwnProps = getDependsOnOwnProps(props)

                //          props = proxy(stateOrDispatch, ownProps)

                //        }


                //        if (process.env.NODE_ENV !== 'production')

                //          verifyPlainObject(props, displayName, methodName)

                            // 此时得到最后的要添加的props属性

                //        return props

                //      }

                      //  返回proxy

                //      return proxy

                //    }

                //  }


        // 返回一个initMapStateToProps方法(该方法调用时返回proxy)

        const initMapStateToProps = match(mapStateToProps,mapStateToPropsFactories,'mapStateToProps')

        const initMapDispatchToProps = match(mapDispatchToProps, mapDispatchToPropsFactories, 'mapDispatchToProps')

        const initMergeProps = match(mergeProps, mergePropsFactories, 'mergeProps')

        // 调用connectAdvanced、

        // 参数 selectorFactory 初始化每次props改变时要调用的方法(返回新的props给被嵌套的控件)

        // 参数 {selector 计算需要的参数}

        // HOC (Higher-order component)获取一个组件 返回一个高阶组件

        return connectHOC(selectorFactory,{

            // 实参

            initMapStateToProps,

            initMapDispatchToProps,

            initMergeProps,

        })

    }

}

// 将传入的

function match(arg,factories,name){

    for(let i = factories.length -1; i >= 0 ;i--){

        const result = factories[i](arg)

        if(result){

            return result

        }

    }

    return (dispatch,options)=>{

        throw new Error

    }

}

// connectAdvanced

export default function connectAdvanced(

    // 参数  selectorFactory

    // selector function集合,通过state.props.dispatch计算出新的props

    // 组合参数 options.pure? pureFinalPropsSelectorFactory: impureFinalPropsSelectorFactory

    // 

    // export default connnectAdvanced(

        // (dispatch,options)=>

        // (state,props)=>

        // ({ thing:state.things[props.thingId],

        //    saveThing: fields => dispatch(actionCreators.saveThing(props.thingId,fields)),

        //  })

    // )(YourComponent)

    selectorFactory,

    // options object:

    {

    } = {}

){

    // 方法体

    // 给出入的UI组件wrappedComponent 添加需要props,变成高阶组件

    // 参数 基础组件

    return function wrapWithConnect(WrappedComponent){

        // 内部类

        class Connect extends Component{

            constructor(props,context){

                super(props,context)

                this.version = version

                this.state = {}

                this.renderCount = 0

                this.store = props[storeKey]

                this.initSelector();

                this.initSubscription();

            }


            getChildContext(){

                // 传递store

            }

            componentDidMount(){

                //

            }

            componentWillReceiveProps(nextProps){


            }

            shouldComponentUpdate(){


            }

            componentWillUnmount(){


            }

            // 方便通过ref操作组件

            getWrappedInstance(){


            }

            setWrappedInstance(){


            }

            initSelector(){


                const sourceSelector = selectorFactory(this.store.dispatch,selectorFactoryOptions)

                this.selector = makeSelectorStateful(sourceSelector,this.store);

                // function makeSelectorStateful(sourceSelector, store) {

                //    // wrap the selector in an object that tracks its results between runs.

                //    const selector = {

                    // 为selector 添加run方法

                //      run: function runComponentSelector(props) {

                //        try {

                            // mergedProps = mergeProps(stateProps, dispatchProps, ownProps)

                //          const nextProps = sourceSelector(store.getState(), props)

                //          if (nextProps !== selector.props || selector.error) {

                //            selector.shouldComponentUpdate = true

                //            selector.props = nextProps

                //            selector.error = null

                //          }

                //        } catch (error) {

                //          selector.shouldComponentUpdate = true

                //          selector.error = error

                //        }

                //      }

                //    }


                //    return selector


                //  }


                // 调用run(this.props)

                // ->sourceSelector(store.getState(), props)

                // ->mergedProps = mergeProps(stateProps, dispatchProps, ownProps)

                // 传递属性给要封装的组件

                this.selector.run(this.props)

            }

            initSubscription(){

                this.subscription = new Subscription(this.store,parentSub,this.onStateChanged.bind(this))

            }

            onStateChange(){


                this.selector.run(this.props)

            }

            render(){


                return createElement(WrappedComponent,this.addExtraProps(this.selector.props))

            }

        }



        return hoistStatics(Connect,WrappedComponent)

    }

}

// 最后得到的就是新的props

// 1、connect(mapStateToProps,mapDispatchToProps,mergeProps

// 2、connectHOC(selectorFactory,{

//    // initMapStateToProps->initProxySelector->proxy->mapStateToProps 获得传入的props

//    initMapStateToProps,

//    initMapDispatchToProps,

//    initMergeProps,

//    ...

// })

// 3、connectAdvanced(selectorFactory,{...})

// 4、wrapWithConnect(WrappedComponent) 

//      new Connect()

            // this.selector.run(this.props)

            // 调用run(this.props)

            // ->sourceSelector(store.getState(), props)

            // ->mergedProps = mergeProps(stateProps, dispatchProps, ownProps)

            // 传递属性给要封装的组件


// 5、hoistStatics(Connect,WrappedComponent)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,780评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,424评论 1 305
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,397评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,576评论 0 218
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,997评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,945评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,107评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,850评论 0 208
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,625评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,804评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,285评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,613评论 3 261
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,291评论 3 242
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,164评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,963评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,096评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,886评论 2 278

推荐阅读更多精彩内容