自定義redux庫

自定義redux庫

redux語法功能分析

  1. redux 庫向外暴露下面幾個函數
    • createStore(): 接收的參數爲 reducer 函數, 返回爲 store 對象
    • combineReducers(): 接收包含 n 個 reducer 方法的對象, 返回一個新的 reducer 函數
  2. store 對象的內部結構
    • getState(): 返回值爲內部保存的 state 數據
    • dispatch(): 參數爲 action 對象
    • subscribe(): 參數爲監聽內部 state 更新的回調函數

實現createStore()

實現createStore()的功能react

/** * redux庫主模塊 * 1. redux 庫向外暴露下面幾個函數 - createStore(): 接收的參數爲 reducer 函數, 返回爲 store 對象 - combineReducers(): 接收包含 n 個 reducer 方法的對象, 返回一個新的 reducer 函數 2. store 對象的內部結構 - getState(): 返回值爲內部保存的 state 數據 - dispatch(): 參數爲 action 對象 - subscribe(): 參數爲監聽內部 state 更新的回調函數 */

/** * * 根據指定的reducer函數建立一個store對象 */
export function createStore(reducer) { //接收一個reducer函數

  //用來存儲內部狀態數據的變量,初始值爲調用reducer函數返回的結果(外部指定的默認值)
  let state = reducer(undefined, { type: '@@redux/init' })
  //用來存儲監聽state更新回調函數的數組容器
  const listeners = []
  
  /** * 返回當前內部的state數據 */
  function getState() {
    return state
  }
  /** * 分發action * 1.觸發reducer調用,獲得新的state * 2.保存新的state * 3.調用全部已存在的監視回調 * */
  function dispatch(action) {
    // 1.觸發reducer調用,獲得新的state
    const newState = reducer(state, action)
    // 2.保存新的state
    state = newState
    
    // 3.調用全部已存在的監視回調
    
    listeners.forEach(listener => listener())
  }
  /** * 綁定內部state改變的監聽回調 * 能夠給一個stort綁定多個監聽 */
  function subscribe(listener) {
    //保存到緩存Listener的容器數組中
    listeners.push(listener)
    console.log(listeners)
    console.log('觸發subscribe')
  }
  //返回store對象
  return {
    getState,
    dispatch,
    subscribe
  }
}
/** * * 整合傳入參數對象中的多個reducer函數,返回一個新的reducer * 新的reducer管理的總狀態:{r1:state1,r2:state2} */
export function combineReducers(reducers) {
  return (state, action) => {

  }
}
複製代碼

實現combineReducers

/** * * 整合傳入參數對象中的多個reducer函數,返回一個新的reducer * 新的reducer管理的總狀態:{r1:state1,r2:state2} * reuscers的結構: * { * count: (state=2,action) => 3 * user: (state = {}, action) => {} * } * 要獲得的總狀態的結構 * { * count:count(state.count,action), * user:user(state.user,action) * } */
// const obj = {
// count: (state = 2, action) => 3,
// user: (state = {}, action) => { }
// }

/** * forEach版本 */

export function combineReducers(reducers) {
  //返回一個新的總reducer函數
  //state:總狀態
  return (state = {}, action) => {
    //準備一個總狀態空對象
    const totalState = {}
    //執行reducers中每一個reducer函數獲得一個新的子狀態,並添加到總狀態空對象
    Object.keys(reducers).forEach(key => {
      totalState[key] = reducers[key](state[key], action)
    })
    return totalState
  }
}
/** * reduce版本 */
// export function combineReducers(reducers) {
// //返回一個新的總reducer函數
// //state:總狀態
// return (state = {}, action) => {
// //執行reducers中每一個reducer函數獲得一個新的子狀態,並封裝一個對象容器
// const newState = Object.keys(reducers).reduce((preState, key) => {
// preState[key] = reducers[key](state[key], action)
// return preState
// }, {})
// return newState
// }
// }

//簡潔版本
export function combineReducers(reducers) {
  return (state = {}, action) => {
    return Object.keys(reducers).reduce((pre, key) => {
      pre[key] = reducers[key](state[key], action)
      return pre
    }, {})
  }
}

複製代碼

自定義redux-react

1.react-redux 向外暴露了 2 個 API
  • Provider 組件類redux

  • connect 函數數組

2.Provider 組件
  • 接收 store 屬性緩存

  • 讓全部容器組件均可以看到 store, 從而經過 store 讀取/更新狀態ide

3.connect 函數

接收 2 個參數: mapStateToProps 和 mapDispatchToProps函數

mapStateToProps: 爲一個函數, 用來指定向 UI 組件傳遞哪些通常屬性ui

mapDispatchToProps: 爲一個函數或對象, 用來指定向 UI 組件傳遞哪些函數屬性this

connect()執行的返回值爲一個高階組件: 包裝 UI 組件, 返回一個新的容器組件spa

容器組件會向 UI 傳入前面指定的通常/函數類型屬性code

代碼

/** * react-redux庫的主模塊 * 1) react-redux 向外暴露了 2 個 API a. Provider 組件類 b. connect 函數 * 2) Provider 組件 * 接收 store 屬性 * 讓全部容器組件均可以看到 store, 從而經過 store 讀取/更新狀態 * 3) connect 函數 * 接收 2 個參數: mapStateToProps 和 mapDispatchToProps * mapStateToProps: 爲一個函數, 用來指定向 UI 組件傳遞哪些通常屬性 * mapDispatchToProps: 爲一個函數或對象, 用來指定向 UI 組件傳遞哪些函數屬性 * connect()執行的返回值爲一個高階組件: 包裝 UI 組件, 返回一個新的容器組件 * 容器組件會向 UI 傳入前面指定的通常/函數類型屬性 */
import React from 'react'
import PropTypes from 'prop-types'
/** * 用來向全部容器組件提供store的組件類 * 經過context向全部的容器組件提供store */
export class Provider extends React.Component {

  static propTypes = {
    store: PropTypes.object.isRequired //聲明接收store
  }
  /** * 聲明提供context的數據名稱和類型 */
  static childContextTypes = {
    store: PropTypes.object
  }
  /** * 向全部有聲明子組件提供包含要傳遞數據的context對象 */
  getChildContext() {
    return { store: this.props.store }
  }
  render() {
    //返回渲染<Provider> 的全部子節點
    return this.props.children
  }
}

/** * connect高階函數:接收 mapStateToProps 和 mapDispatchToProps ,返回一個高階組件函數 * 高階組件:接收一個UI組件,返回一個容器組件 */

export function connect(mapStateToProps, mapDispatchToProps) {
  //返回高階組件函數
  return (UIComponent) => {
    //返回容器組件
    return class ContainerComponent extends React.Component {

      /** * 聲明接收的context數據的類型 */
      static contextTypes = {
        store: PropTypes.object
      }
      constructor(props, context) {
        super(props)
        console.log('ContainerComponent', context.store)
        //獲得store
        const { store } = context
        //獲得包含全部通常屬性的對象
        const stateProps = mapStateToProps(store.getState()) //而且把state中的數據傳遞過去

        //將全部通常屬性做爲容器組件的狀態數據
        this.state = { ...stateProps }

        //獲得包含全部函數屬性的對象
        let dispatchProps
        //判斷傳遞過來的是不是函數
        if (typeof mapDispatchToProps === 'function') {
          //函數的狀況
          dispatchProps = mapDispatchToProps(store.dispatch)//而且把dispatch傳遞過去
        } else { //對象的狀況
          dispatchProps = Object.keys(mapDispatchToProps).reduce((pre, key) => {
            const actionCreator = mapDispatchToProps[key]
            pre[key] = (...args) => store.dispatch(actionCreator(...args)) //參數透傳
            return pre
          }, {})
        }

        //保存到組件上
        this.dispatchProps = dispatchProps

        //綁定store的state變化的監聽
        store.subscribe(() => {  // store內部的狀態數據發生了變化
          console.log('11')
          //更新容器組件 ==> UI更新
          this.setState(mapStateToProps(store.getState()))
        })
      }

      render() {
        //返回UI組件的標籤
        return <UIComponent {...this.state} {...this.dispatchProps} /> } } } } 複製代碼

使用:

和react-redux使用方法同樣

相關文章
相關標籤/搜索