You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
importcreateStorefrom'./createStore'importcombineReducersfrom'./combineReducers'importbindActionCreatorsfrom'./bindActionCreators'importapplyMiddlewarefrom'./applyMiddleware'importcomposefrom'./compose'importwarningfrom'./utils/warning'import__DO_NOT_USE__ActionTypesfrom'./utils/actionTypes'/* * This is a dummy function to check if the function name has been altered by minification. * If the function has been minified and NODE_ENV !== 'production', warn the user. */functionisCrushed(){}if(process.env.NODE_ENV!=='production'&&typeofisCrushed.name==='string'&&isCrushed.name!=='isCrushed'){warning('You are currently using minified code outside of NODE_ENV === "production". '+'This means that you are running a slower development build of Redux. '+'You can use loose-envify (https://github.com/zertosh/loose-envify) for browserify '+'or setting mode to production in webpack (https://webpack.js.org/concepts/mode/) '+'to ensure you have the correct code for your production build.')}export{createStore,combineReducers,bindActionCreators,applyMiddleware,compose,__DO_NOT_USE__ActionTypes}
exportdefaultfunctioncreateStore(reducer,preloadedState,enhancer){// 判断接受的参数个数,来指定 reducer 、 preloadedState 和 enhancerif(typeofpreloadedState==='function'&&typeofenhancer==='undefined'){enhancer=preloadedStatepreloadedState=undefined}if(typeofenhancer!=='undefined'){if(typeofenhancer!=='function'){thrownewError('Expected the enhancer to be a function.')}returnenhancer(createStore)(reducer,preloadedState)}if(typeofreducer!=='function'){thrownewError('Expected the reducer to be a function.')}letcurrentReducer=reducer// 存储当前的reducerletcurrentState=preloadedState// 存储当前的状态letcurrentListeners=[]// 储存当前的监听函数列表letnextListeners=currentListeners// 储存下一个监听函数列表letisDispatching=false//是否在执行reducer}
// 接上述代码,这里不在重复functiongetState(){if(isDispatching){thrownewError('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.')}returncurrentState}
这里判断是否在执行reducer,返回当前的最新状态state.
dispatch
functiondispatch(action){if(!isPlainObject(action)){thrownewError('Actions must be plain objects. '+'Use custom middleware for async actions.')}if(typeofaction.type==='undefined'){thrownewError('Actions may not have an undefined "type" property. '+'Have you misspelled a constant?')}if(isDispatching){thrownewError('Reducers may not dispatch actions.')}try{isDispatching=truecurrentState=currentReducer(currentState,action)}finally{isDispatching=false}constlisteners=(currentListeners=nextListeners)for(leti=0;i<listeners.length;i++){constlistener=listeners[i]listener()}returnaction}
dispatch接受一个参数action,action 是把数据从应用传到 store 的有效载荷,它是 store 数据的唯一来源,action包含type和payload,payload表示最新的状态state,type代表操作类型。传入action后会首先运行reducer,reducer接收action和当前状态state,reducer只判断type属性来返回最新的state。
dispatch还会触发整个监听函数列表,所以最后整个监听函数列表都会按顺序执行一遍。dispatch返回值就是传入的action。
function subscribe(listener) {
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#subscribe(listener) for more details.'
)
}
let isSubscribed = true
ensureCanMutateNextListeners()
nextListeners.push(listener)
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#subscribe(listener) for more details.'
)
}
isSubscribed = false
ensureCanMutateNextListeners()
const index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1)
}
}
functionreplaceReducer(nextReducer){if(typeofnextReducer!=='function'){thrownewError('Expected the nextReducer to be a function.')}currentReducer=nextReducerdispatch({type: ActionTypes.REPLACE})}
redux的源码并不是很多,大致只分为下列几个文件:
index.js是整个代码的入口,主要是判断代码在非生成环境是否压缩暴露出createStore,combineReducers,bindActionCreators,applyMiddleware等几个方法,如果没有这发出警告⚠️
createStore.js
createStore是redux中一个非常重要的API,createStore会生成一个store,维护一个状态树,里面是全局的state,
createStore接受三个参数,分别为reducer纯函数,初始状态,增强器(即 applyMiddleware()返回的东西以及其他的中间件)用法如下:
createStore生成的store提供了dispath,subscribe,getState,replaceReducer,observable等方法,接下来逐一分析。
首先判定参数个数,分别指定三个参数,接着判断enhancer是否存在并且为函数则调用enhancer,并且终止当前函数执行,前面的判断基本上是对三个参数对判断。接下来是对当前状态及reducer的存储。
getState
这里判断是否在执行reducer,返回当前的最新状态state.
dispatch
dispatch接受一个参数action,action 是把数据从应用传到 store 的有效载荷,它是 store 数据的唯一来源,action包含type和payload,payload表示最新的状态state,type代表操作类型。传入action后会首先运行reducer,reducer接收action和当前状态state,reducer只判断type属性来返回最新的state。
dispatch还会触发整个监听函数列表,所以最后整个监听函数列表都会按顺序执行一遍。dispatch返回值就是传入的action。
subscribe
ensureCanMutateNextListeners 会根据当前的监听函数列表生成下一个监听函数列表。
subscribe会接受一个listener函数,首先运行ensureCanMutateNextListeners生成下一个监听列表,然后向列表中添加进新的监听函数listenner,subscribe的返回值是一个unsubscribe,是一个解绑函数,调用该解绑函数,会将已经添加的监听函数删除,该监听函数处于一个闭包之中,会一直存在,所以在解绑函数中能删除该监听函数。这就是redux精妙之处。
replaceReducer
顾名思义replaceReducer的意思就是替换掉reducer,replaceReducer接受一个reducer替换的当前的reducer,之后立即执行dispatch({ type: ActionTypes.INIT }) ,用来初始化store的状态。
replaceReducer的使用场景,分别是:
observable
该方法并不是暴露给使用者的,一般用于内部,在测试的时候会用到,这里不深究。
redux源码分析(二)
The text was updated successfully, but these errors were encountered: