前言了解了上一章【Redux源码分析系列(一)——Redux的实现思路】后,我们正式进入源码分析~Redux其实是用来帮忙的us一个管理状态的框架,它给我们暴露了四个接口,分别是:createStorecombineReducersbindActionCreatorsapplyMiddlewarecompose这篇文章来分析一下createStore,我来分析一下~INIT这个方法是为redux预留的,用于初始化reducer的状态exportconstActionTypes={INIT:'@@redux/INIT'}createStore的作用是创建一个store来管理app的状态。改变状态的唯一方法是分派一个动作并最终返回一个对象。return{dispatch,subscribe,getState,replaceReducer,[$$observable]:observable}不过replaceReducer,和[$$observable]:不常用~所以这里只分析前三个接口。createStore在一个应用中只能有一个商店。如果要指定不同的状态对应不同的动作,可以使用combineReducers组合不同的reducer。参数:reducer(function):通过传入当前状态和action,计算出下一个状态,并返回。preloadedState(any):initialstateenhancer(function):增强store的功能,使其具有第三方功能,比如middleware中唯一的enhancer.Redux是applyMiddleware()exportdefaultfunctioncreateStore(reducer,preloadedState,enhancer){//first段说的是当第二个参数不传preloadedState,而是直接传function时,会直接把这个function当作enhancerif(typeofpreloadedState==='function'&&typeofenhancer==='undefined'){enhancer=preloadedStatepreloadedState=undefined}//当传入第三个参数但不是函数时,会报错')}//关键的就是这样。上一篇讲applyMiddleware的时候介绍过这样做的意义。//其实就是在applyMiddleware中做createStore,转锅。returnenhancer(createStore)(reducer,preloadedState)}if(typeofreducer!=='function'){thrownewError('Expectedthereducertobeafunction.')}letcurrentReducer=reducerletcurrentState=preloadedStateletcurrentListeners=[]letnextListeners=currentListenersletisDispatching=false}以上是第一部分验证后参数的正确性,我们终于可以做点正经事了。createStore最终会返回一个对象。{dispatch,subscribe,getState}接下来我们看看里面做了什么:getStategetState的作用是返回当前state的状态。没什么好说的~functiongetState(){returncurrentState}订阅函数:添加Listening函数监听器,每次dispatchaction都会调用。参数:listener(function):每次dispatchaction都会调用的函数return:return一个移除listener的函数//这个函数的作用是,如果找到nextListeners并且nextListeners指向同一个栈,那么浅拷贝一个functionensureCanMutateNextListeners(){if(nextListeners===nextListeners){nextListeners=currentListeners.slice()}}functionsubscribe(listener){if(typeoflistener!=='function'){thrownewError('Expectedlistenertobeafunction.')}letisSubscribed=trueensureCanMutateNextListeners()//将被监听的函数直接放入nextListenersnextListeners.push(listener)returnfunctionunsubscribe(){//如果已经移除,直接返回if(!isSubscribed){return}isSubscribed=falseensureCanMutateNextListeners()//如果没有移除,先找到位置,通过splice移除constindex=nextListeners.indexOf(listener)nextListeners.splice(index,1)}}使用时可以使用:constunsubscribe=store.subscribe(()=>console.log(store.getState()))unsubscribe()dispatchdispatchdispatch是一个关键函数~其实它的作用就是触发状态的改变。参数:action(object),是描述发生了什么的对象,其中type为必填属性。返回:这个传入对象函数dispatch(action){if(!isPlainObject(action)){thrownewError('Actionsmustbeplainobjects.'+'Usecustommiddlewareforasyncactions.')}//if(typeofaction.type==='undefined'){thrownewError('Actionsmaynothaveanundefined"type"property.'+'Haveyoumisspelledaconstant?')}//为了防止多个dispatch请求同时改变状态,必须在上一个dispatch结束后才能调度下一个if(isDispatching){thrownewError('Reducersmaynotdispatchactions.')}try{isDispatching=truecurrentState=currentReducer(currentState,action)}finally{isDispatching=false}//调度时,将nextListeners重新分配给currentListeners,constlisteners=currentListeners=nextListenersfor(leti=0;i
