redux 源码解析之createStore
2019-06-12 本文已影响0人
小旎子_8327
目录结构
image.png工具类
actionTypes
isPlainObject
waring
src
createStore.js:
先看看createStore方法
export default function createStore(reducer, preloadedState, enhancer) {……}
用法举例:const store=Redux.createStore(reducers);
第一步:参数校验
期望:reducer、enhancer是一个function、preloadedState是个对象
//一、如果preloadedState是个function或者多输了一个参数,报错
if (
(typeof preloadedState === 'function' && typeof enhancer === 'function') ||
(typeof enhancer === 'function' && typeof arguments[3] === 'function')
) {
throw new Error(
'It looks like you are passing several store enhancers to ' +
'createStore(). This is not supported. Instead, compose them ' +
'together to a single function'
)
}
//二、如果preloadedState是个function,且第三个参数enhancer未输入,则将第二个参数当作第三个参数使用
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
enhancer = preloadedState
preloadedState = undefined
}
//如果第三个参数enhancer输入,但是不是个函数,报错,如果是函数,返回enhancer的闭包调用的结果。
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function.')
}
return enhancer(createStore)(reducer, preloadedState)
}
//如果reducer不是个函数,报错
if (typeof reducer !== 'function') {
throw new Error('Expected the reducer to be a function.')
}
怎么样,看起来是不是很简单!
第二步:变量的声明与设置
let currentReducer = reducer
let currentState = preloadedState
let currentListeners = []
let nextListeners = currentListeners
let isDispatching = false
第三步:声明方法
dispatch,
subscribe,
getState,
replaceReducer,
[$$observable]: observable
dispatch:
function dispatch(action) {
//判断参数action是否是纯函数,不是报错
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. ' +
'Have you misspelled a constant?'
)
}
//判断当前是否有执行其他的reducer操作
if (isDispatching) {
throw new Error('Reducers may not dispatch actions.')
}
//执行
//设置isDispatching为true,防止后续的action进来触发reducer操作
//根据action触发状态更新
try {
isDispatching = true
currentState = currentReducer(currentState, action)
} finally {
isDispatching = false
}
//当前状态设置完毕后,执行监听函数
const listeners = (currentListeners = nextListeners)
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
}
//返回参数
return action
}
replaceReducer
参数校验 判断参数nextReducer是不是function
触发state更新操作
function replaceReducer(nextReducer) {
if (typeof nextReducer !== 'function') {
throw new Error('Expected the nextReducer to be a function.')
}
currentReducer = nextReducer
dispatch({ type: ActionTypes.REPLACE })
}
getState
获取当前状态
function getState() {
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
}
subscribe
function subscribe(listener) {
//参数校验
if (typeof listener !== 'function') {
throw new Error('Expected the listener to be a function.')
}
//如果reducer正在执行,报错
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)
}
}