Redux源碼解讀

今天向大家簡單介紹下Redux源碼,若有理解差誤,歡迎在下面留言~

Redux源碼地址:https://github.com/reactjs/redux/tree/master/src

大家可以看到Redux目錄結構為

redux.png

我們只介紹最重要的一個文件夾createStore.js


import isPlainObject from 'lodash/isPlainObject'
import $$observable from 'symbol-observable'


export const ActionTypes = {

INIT: '@@redux/INIT'   //這就是當你在創建一個store時,最開始的action.type值

}

/*
參數reducer就是你傳入的要更改state的函數
參數preloadedState是可選參數,指初始state
參數enhancer也是可選,一般不用
*/
export default function createStore(reducer, preloadedState, enhancer) {

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.')

}

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()

}

}

//得到當前的state值
function getState() {

return currentState

}

/*
參數listener是一個監聽函數
返回值為一個取消監聽的函數
*/
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)

}

}

/*
參數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.')

}

try {

isDispatching = true

//現在的currentReducer就是你傳入的reducer,執行這個函數對state進行更新,返回給當前的currentState。
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

}

/**

 * Replaces the reducer currently used by the store to calculate the state.

 *

 * You might need this if your app implements code splitting and you want to

 * load some of the reducers dynamically. You might also need this if you

 * implement a hot reloading mechanism for Redux.

 *

 * @param {Function} nextReducer The reducer for the store to use instead.

 * @returns {void}

 */

function replaceReducer(nextReducer) {

if (typeof nextReducer !== 'function') {

throw new Error('Expected the nextReducer to be a function.')

}

currentReducer = nextReducer

dispatch({ type: ActionTypes.INIT })

}

/**

 * Interoperability point for observable/reactive libraries.

 * @returns {observable} A minimal observable of state changes.

 * For more information, see the observable proposal:

 * https://github.com/zenparsing/es-observable

 */

function observable() {

const outerSubscribe = subscribe

return {

/**

 * The minimal observable subscription method.

 * @param {Object} observer Any object that can be used as an observer.

 * The observer object should have a `next` method.

 * @returns {subscription} An object with an `unsubscribe` method that can

 * be used to unsubscribe the observable from the store, and prevent further

 * emission of values from the observable.

 */

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

}

}

}


//初始化時的action
dispatch({ type: ActionTypes.INIT })

//返回四個方法,分別完成相應的功能
return {

    dispatch,
    subscribe,
    getState,
    replaceReducer,
    [$$observable]: observable
}
}

當我們使用createStore(reducer)函數時,會返回四個方法供我們使用。當用戶在view層進行數據操作時,這時就有相應的action產生,使用store.dispatch(action)來執行reducer函數對state進行更新,這樣通過getState()就可以獲取最新的state在組件中進行動態顯示。

大家可以通過官網上的Counter實例驗證一下。

代碼地址:https://github.com/reactjs/redux/tree/master/examples/counter

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 前言 redux并不局限于flux與react。redux 自身保持簡潔以便適配各種場景,讓社區發展出各種 red...
    yeatszhang閱讀 726評論 0 49
  • http://gaearon.github.io/redux/index.html ,文檔在 http://rac...
    jacobbubu閱讀 80,055評論 35 198
  • "react-redux": "^5.0.6" redux和react之間的橋梁是react的context,re...
    別過經年閱讀 759評論 0 1
  • 一、CMS管理系統功能 CMS是ContentManagementSystem的縮寫,意為"內容管理系統"。 CM...
    默默先生Alec閱讀 5,407評論 0 7
  • 原來喜歡一個人是這樣的感覺。 我從不知道。 思念、心焦、和欣喜若狂。 然而有一天,我的世界變成了無窮無盡的黑暗, ...
    ouenglli閱讀 196評論 0 0