redux原理 某公司有物流(actionType)、電商(actionType)、廣告(actionType)3塊業務,在公司財務系統(state)統一記錄著三塊業務分別賺取到的資金。某天,電商業務在公司電商平臺銷售了價值100w的商品(action),賺取到的資金通過發票(dispatch)的形 ...
redux原理
某公司有物流(actionType)、電商(actionType)、廣告(actionType)3塊業務,在公司財務系統(state)統一記錄著三塊業務分別賺取到的資金。某天,電商業務在公司電商平臺銷售了價值100w的商品(action),賺取到的資金通過發票(dispatch)的形式送到業務的財務部門,財務部門通過自己業務塊,計算賺取到的利潤(reducer),再更新到財務系統(state)。
核心原理: 通過某個事件action把結果通過dispatch發送到reducer,在reducer中,根據不同的actionType對數據做不同的業務處理,然後把最後的結果更新到state樹中。
由於的幾位老闆對公司的資金盯著很緊,要時刻關註資金的變化,於是,就設置了當資金有變動事件(subscribe),就發簡訊告訴他(listener)。
原理:redux通過內置了一個listeners數組,允許外部訂閱state數據變動事件,當state樹種的數據發生變化,就會通知所有的監聽事件。
API 講解
function createStore(reducer, preloadedState, enhancer)
createStore方法中,初始化了整個redux環境。preloadedState作為state樹的初始值。此方法返回了redux開放的介面,操作redux的state,只能通過返回來的api去操作。
createStore返回返回來的api:
return { dispatch, subscribe, getState, replaceReducer, [$$observable]: observable }
store.getState: 返回當前redux維護的state對象;
store.subscribe: 可以通過此介面註冊訂閱事件,即當redux的state被訪問時(不管有沒有修改到state的數據),redux就會遍歷所有已註冊的事件。
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) } }
store.dispatch: 在事件action運行後,通過dispatch把結果推送到reducer中。action的結果必須為普通的js對象,並且必須包含一個type屬性,在reducer中可以根據type去對數據做不同的業務處理,然後更新到相應的state。
在reducer之後,無論數據有沒有發生變化,都會遍歷所有的監聽事件。
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 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 }
整個單頁面應用僅需調用1次createStore方法,然後確保初始化後的對象全局可用,這樣才能達到通過redux來統一管理數據。