何為Redux,為什么Redux之類的概念東西我這邊就不重復(fù)贅述了,可進(jìn)入Redux官網(wǎng)查閱,以下是我在學(xué)習(xí)Redux的源碼的一些個人總結(jié).
我們可以先看看官方的文檔,都有哪些API,從中也可以看出Redux中的一些方法是如何演化出來的.我們先看看index.js文件中的內(nèi)容,代碼有省略部分,最好是拿著源碼一起看,Redux本身代碼量并不大,只是其中用了很多的函數(shù)柯里化的方式,看著會比較晦澀
// index.js
export {
createStore,
combineReducers,
bindActionCreators,
applyMiddleware,
compose
}
從以上代碼可以看出來,就是Redux提供的API
createStore
import isPlainObject from 'lodash/isPlainObject'
import $$observable from 'symbol-observable'
/**
*這就是初始化store狀態(tài)樹的action type
*/
export const ActionTypes = {
INIT: '@@redux/INIT'
}
/**
* 此函數(shù)接受三個參數(shù),第一個參數(shù)是一個函數(shù),就是我們的reduce函數(shù),返回一個state
*/
export default function createStore(reducer, preloadedState, enhancer) {
/**當(dāng)preloadedState為函數(shù)且enhancer不存在時,將preloadedState賦值給enhancer并且將createStore傳*入此函數(shù)
*/
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方法返回的組合函數(shù)而得到
*/
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()
}
}
/**
* 讀取當(dāng)前整個狀態(tài)樹
*/
function getState() {
return currentState
}
/**
* dispatch訂閱方法,當(dāng)調(diào)用此方法時會在事件監(jiān)聽器中加入監(jiān)聽函數(shù),當(dāng)dispatch了一個action時,所有訂
*閱的方法都會執(zhí)行,此方法執(zhí)行完成會返回一個取消訂閱方法,用于取消訂閱事件
*/
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函數(shù)接受一個為對象的參數(shù),其中必須包含一個type屬性,會將新的state賦值給currentState,并且會執(zhí)行所有subscribe過的函數(shù),并返回當(dāng)前的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.')
}
/** 改變當(dāng)前dispatching狀態(tài)為true,并且將更改后的state賦值給當(dāng)前state
*/
try {
isDispatching = true
currentState = currentReducer(currentState, action)
} finally {
isDispatching = false
}
// 當(dāng)觸發(fā)dispatching函數(shù)時,所有訂閱的函數(shù)都會被觸發(fā)
const listeners = currentListeners = nextListeners
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
}
return action
}
/**
* 此方法會將傳入的reducer替換當(dāng)前的reducer并進(jìn)行Store初始化
*/
function replaceReducer(nextReducer) {
if (typeof nextReducer !== 'function') {
throw new Error('Expected the nextReducer to be a function.')
}
currentReducer = nextReducer
dispatch({ type: ActionTypes.INIT })
}
/**
*不直接提供給開發(fā)者使用
*/
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
}
}
}
// 當(dāng)一個store被創(chuàng)建的時候,會觸發(fā)dispatch來初始化state
dispatch({ type: ActionTypes.INIT })
return {
dispatch,
subscribe,
getState,
replaceReducer,
[$$observable]: observable
}
}
createStore所作的事情其實很簡單,主要的一個流程是,創(chuàng)建store,初始化state,返回一系列的方法,每個方法具體干了哪些事情,在上面的代碼中都已經(jīng)注釋好了.其中有一些其他的波折的東西,我們一會會介紹
applyMiddleware
import compose from './compose'
/**
*這個方法就是將一系列的中間件作為參數(shù),將返回的函數(shù)作為createStore的第二個參數(shù)調(diào)用,最終結(jié)果
*仍然會返回store提供的各個方法組成的對象,只是其中的dispatch方法是各個中間件組合成的一個組合
* 函數(shù),使得在調(diào)用dispatch的時候會經(jīng)過各個中間件
*/
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方法,返回值為函數(shù),通過compose方法整合出組合函數(shù)
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
applyMiddleware的方法主要是通過compose將各個中間件整合成一個組合函數(shù),通過將store.dispatch傳入函數(shù)中進(jìn)行層層過濾,最終返回一個store
compose
/**
* 從右到左整合成組合函數(shù)
*/
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,此函數(shù)在createStore的調(diào)用過程中,會將各個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對應(yīng)每一個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創(chuàng)建函數(shù)和之前創(chuàng)造的store所得到的dispatch方法傳入,返回一個action綁定函數(shù),調(diào)用這個綁定函數(shù)會自動dispatch利用actionCreate所創(chuàng)建的action