何为Redux,为什么Redux之类的概念东西我这边就不重复赘述了,可进入Redux官网查阅,以下是我在学习Redux的源码的一些个人总结.
我们可以先看看官方的文档,都有哪些API,从中也可以看出Redux中的一些方法是如何演化出来的.我们先看看index.js文件中的内容,代码有省略部分,最好是拿着源码一起看,Redux本身代码量并不大,只是其中用了很多的函数柯里化的方式,看着会比较晦涩
// index.js
export {
createStore,
combineReducers,
bindActionCreators,
applyMiddleware,
compose
}
从以上代码可以看出来,就是Redux提供的API
createStore
import isPlainObject from 'lodash/isPlainObject'
import $$observable from 'symbol-observable'
/**
*这就是初始化store状态树的action type
*/
export const ActionTypes = {
INIT: '@@redux/INIT'
}
/**
* 此函数接受三个参数,第一个参数是一个函数,就是我们的reduce函数,返回一个state
*/
export default function createStore(reducer, preloadedState, enhancer) {
/**当preloadedState为函数且enhancer不存在时,将preloadedState赋值给enhancer并且将createStore传*入此函数
*/
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
enhancer = preloadedState
preloadedState = undefined
}
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function.')
}
/**
*此处返回store提供的一些方法,如此处最后返回对象,只是其中的dispatch不一样,由applyMidware方法返回的组合函数而得到
*/
return enhancer(createStore)(reducer, preloadedState)
}
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
function ensureCanMutateNextListeners() {
if (nextListeners === currentListeners) {
nextListeners = currentListeners.slice()
}
}
/**
* 读取当前整个状态树
*/
function getState() {
return currentState
}
/**
* dispatch订阅方法,当调用此方法时会在事件监听器中加入监听函数,当dispatch了一个action时,所有订
*阅的方法都会执行,此方法执行完成会返回一个取消订阅方法,用于取消订阅事件
*/
function subscribe(listener) {
if (typeof listener !== 'function') {
throw new Error('Expected listener 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)
}
}
/**
* dispatch函数接受一个为对象的参数,其中必须包含一个type属性,会将新的state赋值给currentState,并且会执行所有subscribe过的函数,并返回当前的action
*/
function dispatch(action) {
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.')
}
/** 改变当前dispatching状态为true,并且将更改后的state赋值给当前state
*/
try {
isDispatching = true
currentState = currentReducer(currentState, action)
} finally {
isDispatching = false
}
// 当触发dispatching函数时,所有订阅的函数都会被触发
const listeners = currentListeners = nextListeners
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
}
return action
}
/**
* 此方法会将传入的reducer替换当前的reducer并进行Store初始化
*/
function replaceReducer(nextReducer) {
if (typeof nextReducer !== 'function') {
throw new Error('Expected the nextReducer to be a function.')
}
currentReducer = nextReducer
dispatch({ type: ActionTypes.INIT })
}
/**
*不直接提供给开发者使用
*/
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
}
}
}
// 当一个store被创建的时候,会触发dispatch来初始化state
dispatch({ type: ActionTypes.INIT })
return {
dispatch,
subscribe,
getState,
replaceReducer,
[$$observable]: observable
}
}
createStore所作的事情其实很简单,主要的一个流程是,创建store,初始化state,返回一系列的方法,每个方法具体干了哪些事情,在上面的代码中都已经注释好了.其中有一些其他的波折的东西,我们一会会介绍
applyMiddleware
import compose from './compose'
/**
*这个方法就是将一系列的中间件作为参数,将返回的函数作为createStore的第二个参数调用,最终结果
*仍然会返回store提供的各个方法组成的对象,只是其中的dispatch方法是各个中间件组合成的一个组合
* 函数,使得在调用dispatch的时候会经过各个中间件
*/
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
const store = createStore(reducer, preloadedState, enhancer)
let dispatch = store.dispatch
let chain = []
// 使用store提供的getState方法和dispatch方法供各个中间件使用
const middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
// 将所有的中间件中传入store实例提供的getState和dispatch方法,返回值为函数,通过compose方法整合出组合函数
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
applyMiddleware的方法主要是通过compose将各个中间件整合成一个组合函数,通过将store.dispatch传入函数中进行层层过滤,最终返回一个store
compose
/**
* 从右到左整合成组合函数
*/
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)))
}
combineReducers
export default function combineReducers(reducers) {
const reducerKeys = Object.keys(reducers)
const finalReducers = {}
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') {
finalReducers[key] = reducers[key]
}
}
const finalReducerKeys = Object.keys(finalReducers)
let unexpectedKeyCache
if (process.env.NODE_ENV !== 'production') {
unexpectedKeyCache = {}
}
let shapeAssertionError
try {
assertReducerShape(finalReducers)
} catch (e) {
shapeAssertionError = e
}
// 最终返回的一个reducer,此函数在createStore的调用过程中,会将各个reducer的state组合成一个
//完整的state
return function combination(state = {}, action) {
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 = {}
for (let i = 0; i < finalReducerKeys.length; i++) {
const key = finalReducerKeys[i]
const reducer = finalReducers[key]
const previousStateForKey = state[key]
const nextStateForKey = reducer(previousStateForKey, action)
if (typeof nextStateForKey === 'undefined') {
const errorMessage = getUndefinedStateErrorMessage(key, action)
throw new Error(errorMessage)
}
nextState[key] = nextStateForKey
hasChanged = hasChanged || nextStateForKey !== previousStateForKey
}
return hasChanged ? nextState : state
}
以上代码的作用就是将多个拆分好的reducer最终组合成一个完整的reducer,其中store的key对应每一个state的key
bindActionCreators
function bindActionCreator(actionCreator, dispatch) {
return (...args) => dispatch(actionCreator(...args))
}
/**
*/
export default function bindActionCreators(actionCreators, dispatch) {
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"?`
)
}
const keys = Object.keys(actionCreators)
const boundActionCreators = {}
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
const actionCreator = actionCreators[key]
if (typeof actionCreator === 'function') {
boundActionCreators[key] = bindActionCreator(actionCreator, dispatch)
}
}
return boundActionCreators
}
以上代码的主要作用就是将action创建函数和之前创造的store所得到的dispatch方法传入,返回一个action绑定函数,调用这个绑定函数会自动dispatch利用actionCreate所创建的action