• Redux源码分析之createStore


    createStore是一个高阶函数,主要作用是完成store的初始化

    createStore(reducer,preloadedState,enhancer)

    执行createStore完成状态初始化的时候,会在内部调用dispatch传递一个type为init的action, 并且返回一个store对象, 这也是唯一的一次非用户生成的action调度

    export default function createStore(reducer, preloadedState, enhancer) {
    
      // 只传两个参数并且第二个参数是函数的情况下,将其作为增强函数enhancer, 如createStore(reducer,applyMiddleware(middleWare))
      if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
          enhancer = preloadedState
          preloadedState = undefined
      }
    
      if (typeof enhancer !== 'undefined') {
        if (typeof enhancer !== 'function') {
          throw new Error('Expected the enhancer to be a function.')
        }
        return enhancer(createStore)(reducer, preloadedState)
      }
    
      let currentReducer = reducer
      let currentState = preloadedState // 通过闭包维持一份createStore的state tree,更新时,current指针将指向dispatch生成的new state tree,  通过getStateapi对外暴露最新的state tree
      let currentListeners = []  // subscribe方法收集的订阅
      let nextListeners = currentListeners  // 用于调用ensureCanMutateNextListeners 浅拷贝一份list,防止用户在dispatching时调用subscribe/unsubscribe出现bug
      let isDispatching = false // 是否正在更新state
     
      function dispatch(action) {
        try {
          isDispatching = true
          // 改变当前状态
          currentState = currentReducer(currentState, action)
        } finally {
          isDispatching = false
        }
        // 在dispatch改变当前状态之后立即执行所有通过subscribe的函数,执行listener主要用于在更新状态之后做些什么事情,比如视图的render操作,我们可以根据最新的状态去渲染视图
        // 这种方式有一个缺点就是,不论你消费的数据有没有变化,只要你使用subscribe订阅了store,都会执行订阅函数
        // 也就是说,redux并不识别具体的订阅者,而是统一广播通知,但这一功能被react-redux实现了
        const listeners = (currentListeners = nextListeners)
        for (let i = 0; i < listeners.length; i++) {
          const listener = listeners[i]
          listener()
        }
        return action
      }
      
    
      dispatch({ type: ActionTypes.INIT })
      
      return {
        dispatch,
        subscribe,
        getState,
        replaceReducer,
        [$$observable]: observable
      }
    }
    
    折叠

    createStore的几个主要api

    • dispatch
    • subscribe/unsubscribe
    • getState

    dispatch

    负责响应用户的动作,派发action给reducer从而获取最新的视图状态

    dispatch在初始化的时候由redux自身调用一次init action,其他时候都是用户由派发action调用

    流程:

    1. dispatch将store的currentState指针指向reducer返回的new state
    2. 向用户广播通过subscribe注册的所有订阅
    3. 通过getState向用户暴露currentState
      function dispatch(action) {
    
        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
      }
    

    subscribe

    store.subscribe(listener)
    订阅redux 状态变化,一旦状态发生变化就执行所有的订阅函数,同时返回一个取消订阅的函数unsubscribe

      function subscribe(listener) {
        let isSubscribed = true
        nextListeners.push(listener)
        return function unsubscribe() {
          if (!isSubscribed) {
            return
          }
          isSubscribed = false
          const index = nextListeners.indexOf(listener)
          nextListeners.splice(index, 1)
          currentListeners = null
        }
      }
    

    getState

    createStore通过闭包维持一份state tree。
    状态更新时, currentState指针将指向dispatch生成的new state tree, 并通过getState向外暴露

      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
      }
    
  • 相关阅读:
    CAT1 4G+以太网开发板腾讯云手机微信小程序显示温度和下发控制
    【黑马头条之项目部署_持续集成Jenkins】
    css毛玻璃效果/el-progress进度条渐变/axios的基本使用/跨域配置/关闭eslint验证
    iPhone NFC 设置教程(门禁卡/公交卡/校园卡等等)
    海康威视综合安防管理平台任意文件上传
    SpringBoot工程打包与运行(Windows版)
    对于html和css初学者,你有什么值得推荐的简单的网页适合练习?
    JShaman JavaScript混淆加密工具,中英版本区别
    互联网扭蛋机小程序:打破传统扭蛋机的局限,提高销量
    ElasticSearch- Mapping
  • 原文地址:https://www.cnblogs.com/ltfxy/p/16424242.html