zoukankan      html  css  js  c++  java
  • redux教程之源码解析createStore

    redux源码
    redux的源码很简单,分为以下几部分
    • createStore
    • combineReducers
    • applyMiddleware
    • compose
    • bindActionCreators
     
    createStore即入口函数生成store,将reducer和middleware关联起来
    combineReducers即将分散的reducer最终合并成一个统一的reducer
    applyMiddleware即将多个中间件一次合并到reducer中,生成一个最终的reducer
    compose是一个函数,从右到左来组合多个函数。将中间件数组依次从后向前。将后一个中间件包裹在前一个中间件函数中。
    //示例代码
    import { createStore } from 'redux'
    
    function todos(state = [], action) {
      switch (action.type) {
        case 'ADD_TODO':
          return state.concat([action.text])
        default:
          return state
      }
    }
    
    let store = createStore(todos, ['Use Redux'])
    
    store.dispatch({
      type: 'ADD_TODO',
      text: 'Read the docs'
    })
    
    console.log(store.getState())
    // [ 'Use Redux', 'Read the docs' ]
    

    createStore即入口函数:
    export default function createStore(reducer, preloadedState, enhancer) {
       /** 入口参数判断*/
      if (
        (typeof preloadedState === 'function' && typeof enhancer === 'function') ||
        (typeof enhancer === 'function' && typeof arguments[3] === 'function')
      ) {
         /** enhancer即中间件,中间件需要合在一起传入createStore*/
        throw new Error(
          'It looks like you are passing several store enhancers to ' +
            'createStore(). This is not supported. Instead, compose them ' +
            'together to a single function'
        )
      }
    /** preloadedState可以省略*/
      if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
        enhancer = preloadedState
        preloadedState = undefined
      }
    /**middleware需要为函数 */
      if (typeof enhancer !== 'undefined') {
        if (typeof enhancer !== 'function') {
          throw new Error('Expected the enhancer to be a function.')
        }
    
        return enhancer(createStore)(reducer, preloadedState)
      }
    /**即reducer需要为函数, */
      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()
        }
      }
    
      /**
       * Reads the state tree managed by the store.
       *
       * @returns {any} The current state tree of your application.
       */
      /**获取Store的currentState */
      function getState() {
        if (isDispatching) {
          throw new Error(
            'You may not call store.getState() while the reducer is executing. ' +
              'The reducer has already received the state as an argument. ' +
              'Pass it down from the top reducer instead of reading it from the store.'
          )
        }
    
        return currentState
      }
    
      /**绑定监听函数,即reducer执行完后后执行这些函数 */
      function subscribe(listener) {
        if (typeof listener !== 'function') {
          throw new Error('Expected the listener to be a function.')
        }
    
        if (isDispatching) {
          throw new Error(
            'You may not call store.subscribe() while the reducer is executing. ' +
              'If you would like to be notified after the store has been updated, subscribe from a ' +
              'component and invoke store.getState() in the callback to access the latest state. ' +
              'See https://redux.js.org/api-reference/store#subscribe(listener) for more details.'
          )
        }
    
        let isSubscribed = true
        /**新生成一个listener数组,以免push时影响 currentListener*/
        ensureCanMutateNextListeners()
        nextListeners.push(listener)
    
        /**返回一个解除绑定的函数 */
        return function unsubscribe() {
          if (!isSubscribed) {
            return
          }
    
          if (isDispatching) {
            throw new Error(
              'You may not unsubscribe from a store listener while the reducer is executing. ' +
                'See https://redux.js.org/api-reference/store#subscribe(listener) for more details.'
            )
          }
    
          isSubscribed = false
          /**又出现了这个函数,确认是否可以变为下一个监听,z不知道这个函数有什么用 */
          ensureCanMutateNextListeners()
          /**确定解除绑定函数的位置并删除它 */
          const index = nextListeners.indexOf(listener)
          nextListeners.splice(index, 1)
        }
      }
      
      function dispatch(action) {
        /**判断action是否为纯对象 */
        if (!isPlainObject(action)) {
          throw new Error(
            'Actions must be plain objects. ' +
              'Use custom middleware for async actions.'
          )
        }
        /**action必须有type */
        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,且开始执行reducer修改state */
          isDispatching = true
          currentState = currentReducer(currentState, action)
        } finally {
          isDispatching = false
        }
        /**执行完后通知listeners */
        const listeners = (currentListeners = nextListeners)
        for (let i = 0; i < listeners.length; i++) {
          const listener = listeners[i]
          listener()
        }
    
        return action
      }
    
      
      /**替换reducer,且初始化state */
      function replaceReducer(nextReducer) {
        if (typeof nextReducer !== 'function') {
          throw new Error('Expected the nextReducer to be a function.')
        }
    
        currentReducer = nextReducer
        //初始化state
        dispatch({ type: ActionTypes.REPLACE })
      }
    
      
      function observable() {
        const outerSubscribe = subscribe
        return {
          subscribe(observer) {
            if (typeof observer !== 'object' || observer === null) {
              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
          }
        }
      }
    
      // When a store is created, an "INIT" action is dispatched so that every
      // reducer returns their initial state. This effectively populates
      // the initial state tree.
      dispatch({ type: ActionTypes.INIT })
    
      return {
        dispatch,
        subscribe,
        getState,
        replaceReducer,
        [$$observable]: observable
      }
    }
  • 相关阅读:
    数据库连接池
    数据库操作
    cookie/session
    楼梯问题
    Response/Request
    Web
    Exception
    jQuery效果与事件方法
    jQuery基础知识点
    布局的几种形式
  • 原文地址:https://www.cnblogs.com/qdcnbj/p/12687028.html
Copyright © 2011-2022 走看看