redux淺析

redux觀點

redux是一個狀況治理容器,運用redux能夠更好的治理和監測組件之間須要通訊的數據。

redux基本原則

單一數據源

在redux中,全部運用堅持一個數據源,數據源是一個樹形的構造

狀況只讀

狀況只讀意義是不能直接修正,須要經由過程dispatch action體式格局才能夠,返回的是一個新的狀況對象

純函數操縱轉變數據

轉變數據的純函數是指reducer,以下情勢

reducer(state, action)

函數內部通常是switch case這些代碼,函數的效果完全由兩個參決議,一樣的輸入前提,會發生一樣的輸出效果

redux運用

//reducer.js
export default (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1
    case 'DECREMENT':
      return state - 1
    default:
      return state
  }
}
//main.js
import { createStore } from 'redux'
const store = createStore(counter)
store.getState()  //獵取狀況
store.dispatch({ type: 'INCREMENT' })  //轉變狀況

申明 上面是純redux的一個簡樸示例, 目標是轉變store內部計數器的狀況
連繫react運用例子,能夠參考我之前的剖析

redux剖析

redux的中心異常簡約, 供應了中間件機制能夠拓展功用。中心模塊主要有以下幾部份

  createStore,
  combineReducers,
  bindActionCreators,
  applyMiddleware,
  compose

下面順次來剖析,首先是createStore模塊,主要完成邏輯以下

export default function (reducer, preloadedState) {
    let currentState = preloadedState;
    let listeners = [];
    function getState() {
        return currentState
    }
    //派發action
    function dispatch(action) {
        //經由過程舊狀況和新action盤算出新狀況
        currentState = reducer(currentState, action);
        //實行監聽函數
        listeners.forEach(listener => listener());
    }
    //派發了一個行動舉行初始化
    dispatch({ type: '@@redux/INIT' });
    //供外界定閱本堆棧中狀況的變化 
    function subscribe(listener) {
        listeners.push(listener);
        //返回一個作廢定閱函數
        return function () {
            listeners = listeners.filter(item => item != listener)
        }
    }
    return {
        getState, dispatch, subscribe
    }
}

申明 這個模塊主要經由過程閉包的體式格局建立一個store,封裝了處置懲罰邏輯,對外只供應getState(獵取狀況),dispatch(派發action),subscribe(定閱轉變)三個接口。

combineReducers主要完成邏輯以下

export default function combineReducers(reducers) {
    const finalReducerKeys = Object.keys(reducers)
    //返回的是兼并后的reducer
    return function combination(state = {}, action) {
        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]
          //盤算子store中,state的值
          const nextStateForKey = reducer(previousStateForKey, action)
        
          nextState[key] = nextStateForKey
          //假如沒轉變的話,照樣用之前的state
          hasChanged = hasChanged || nextStateForKey !== previousStateForKey
        }
        return hasChanged ? nextState : state
      }
    }
    

申明 源碼有快200行了,斟酌了種種邊境狀況,中心邏輯就上面一點, 和並多個reducer成一個對象

bindActionCreators主要完成邏輯以下

export default function bindActionCreators(actionCreators, dispatch) {
  const keys = Object.keys(actionCreators)
  const boundActionCreators = {}
  for (let i = 0; i < keys.length; i++) {
    const key = keys[i]
    const actionCreator = actionCreators[key]
    //把一個 value 為差別 action creator 的對象,轉成具有同名 key 的對象
    if (typeof actionCreator === 'function') {
    //運用 dispatch 包裝 action creator 以便子組件能夠直接挪用。
      boundActionCreators[key] = function() { return dispatch(actionCreator.apply(this, arguments)) }
    }
  }
  return boundActionCreators
}

申明 唯一會運用到 bindActionCreators 的場景是把 action creator 往下傳到一個組件上,卻不想讓這個組件覺察到 Redux 的存在,而且不願望把 dispatch 或 Redux store 傳給它。

applyMiddleware

export default function applyMiddleware(...middlewares) {
    //下面這句話在create.js中 enhancer(createStore)(reducer, preloadedState)時會實行,目標是建立一個增強版的store
  return (createStore) => (...args) => {
    //照樣挪用原生createStore邏輯舉行初始化建立store
    const store = createStore(...args)
    let dispatch = store.dispatch
    let chain = []
    // 傳遞給中間件運用
    const middlewareAPI = {
      getState: store.getState,
      dispatch: (...args) => dispatch(...args)
    }
    //加工中間件,注入middlewareAPI
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    //構成洋蔥中間件情勢包裹dispatch構造的情勢
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

申明 applyMiddleware中間件機制,能夠在處置懲罰store前後加一些通用處置懲罰,完成這個機制功用最主要,也是最難明白的一步操縱就是compose,見下面剖析。

compose

export default function compose(...funcs) {
  
  return funcs.reduce((a, b) => (...args) => a(b(...args)))
}

申明 將多個函數兼并成一個函數,嵌套實行,舉個例子,比方compose(f, g, h)后就變成f(g(h())),而 函數的實行遞次從右到左,h() g() f()

總結

為了輕易明白,我主要將源碼中癥結主流程邏輯做了擇要簡化輸出,加以解釋申明,分外想說的一點感受就是,在redux生態系統頂用到了大批函數式編程中的一些東西,比方高階函數,以及隨時候不停增進的action行動列表(能夠等價思索以為redux對這個列表舉行reduce操縱),而處置懲罰action的就是純函數理念的reducer,另有處置懲罰異步的中間件thunk函數等等。

參考源碼
“redux”: “3.7.2”,
參考鏈接
https://redux.js.org/

    原文作者:jsdt
    原文地址: https://segmentfault.com/a/1190000014549632
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞