深入理解Redux和React-Redux並完成自己的React和React-redux

React是什麼?

 redux是一個獨立專門用於做狀態管理的JS庫(不是React插件庫),作用:集中式管理react應用中多個組件狀態共享的狀態

React主要有三個大模塊:action Creator、Store、Reducers

接下來主要自己實現一下內容:

1. createStore(reducer) :接收一個reducer函數,返回一個store對象

2. combineReducers(reducers) : 接收一個包含多個reducer函數的對象,返回一個新的reducer函數

3.store 對象

    +  getState() : 得到內部管理的state對象

    +  dispatch(action): 分發action,會觸發reducer調用,返回一個新的狀態,調用所有綁定的listener

    +  subscribe(listener): 訂閱一個state的監視器

createStore的實現

export function createStore(reducer) {
  // 內部保存n個listener的數組
  const listeners = []
  // 內部state
  let state
  //   第一次調用reducer得到初始狀態並保存
  state = reducer(state, { type: '@mini-redux' })
  //  得到內部管理的state對象
  function getState() {
    return state
  }

  function dispatch(action) {
    // 調用reducer,得到新的state 並保存
    state = reducer(state, action)
    // 調用所有listener的監視回調函數
    listeners.forEach(listener => listener())
  }

  // 訂閱一個state的監視器
  function subscribe(listener) {
    listeners.push(listener)
  }
  return { getState, dispatch, subscribe }
}

 conbineReducers的實現:接收一個reducers對象,返回一個新的reducer函數

// 接收一個包含多個reducer函數的對象,返回一個新的reducer函數
export function combineReducers(reducers) {
  return function(state = {}, action) {
    // 這個函數會傳給createStore()
    //  依次調用所有的reducer函數,得到n個新的子狀態,封裝成對象並返回
    // 準備一個用來保存所有新狀態的容器對象
    const newState = {}
    // 包含所有reducer函數名的數組: ['count','msgs']
    const keys = Object.keys(reducers)
    keys.forEach(key => {
      // 得到對應的reducer函數
      const childReducer = reducers[key]
      //   得到對應的子state
      const childState = state[key]
      //    執行子reducer
      const newChildState = childReducer(childState, action)
      //   保存到新的總state中
      newState[key] = newChildState
    })
    // 返回總的新state
    return newState
  }
}

以下是簡寫

export function combineReducers2(reducers) {
  return function(state = {}, action) {
    // 這個函數會傳給createStore()
    //  依次調用所有的reducer函數,得到n個新的子狀態,封裝成對象並返回
    return Object.keys(reducers).reduce((newState, reducerName) => {
      newState[reducerName] = reducers[reducerName](state[reducerName], action)
      return newState
    }, {})
  }
}

這樣就初步完成了自己的redux,理解上述代碼,可以進一步瞭解redux的底層原理,接下來就是React-redux的實現

React-redux主要是兩個模塊:Provider組件,connect函數

Provider組件:爲所有的容器子組件提供store(注意:這裏使用的context語法

代碼實現

const StateContext = React.createContext()
export class Provider extends React.Component {
  static propTypes = {
    store: propTypes.Object.isRequired
  }
  //   爲子組件提供一個包含store的context
  render() {
    return (
      <StateContext.Provider value={this.props.store}>
        {/* 將所有子標籤返回 */}
        {this.props.children}
      </StateContext.Provider>
    )
  }
}

connect函數:將ui組件包裝成一個容器組件

export function connect(mapStateToProps, mapDispatchToProps) {
  // 返回一個函數(接收一個組件)
  return WrapComponent => {
    return class ConnectComponent extends React.Component {
      // 聲明獲取context數據
      static contextType = StateContext
      constructor(props, context) {
        super(props, context)

        // 包含一般屬性的對象
        const stateProps = mapStateToProps(this.context)
        // 包含函數屬性的對象
        const dispatchProps = this.bindActionCreators(mapDispatchToProps)

        // 將所有的一般屬性都保存到state中
        this.state = stateProps
        // 將所有的函數屬性的對象保存到組件對象中
        this.dispatchProps = dispatchProps
      }
      //  根據mapDispatchToProps 返回一個包含分發action的函數的對象
      bindActionCreators = mapDispatchToProps => {
        const keys = Object.keys(mapDispatchToProps)
        return keys.reduce((preDispatchProps, key) => {
          // 添加一個包含dispatch語句的方法
          //   透傳:將函數接受到的參數,原樣傳給內部函數調用
          preDispatchProps[key] = (...args) => {
            //   分發action
            this.context.dispatch(mapDispatchToProps[key](...args))
          }
          return preDispatchProps
        }, {})
      }

      componentDidMount() {
        //  訂閱監聽
        this.context.subscribe(function() {
          // redux中產生了一個新的state
          // 更新當前組件的狀態
          this.setState(mapStateToProps(this.context.getState()))
        })
      }
      render() {
        return <WrapComponent {...this.state} {...this.dispatchProps} />
      }
    }
  }
}

這樣就簡單完成了React-redux的實現,學會了這些代碼可以更加深入的瞭解React-redux的實現原理。大家加油!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章