美文网首页ReactWeb前端之路Web 前端开发
mini-redux系列之一:createStore

mini-redux系列之一:createStore

作者: 2f1b6dfcc208 | 来源:发表于2018-05-12 13:15 被阅读6次

      最近一周看了redux、react-redux的源码,觉得又收获了很多,对于redux不再是停留在应用层面,而是深入底层原理,了解了整个库的设计思路。在读源码的过程中,虽然仍有小部分内容感到晦涩,但是不影响对整个库的理解,同时,自己根据个人理解参照官方库自定义实现了一个简化版的mini-redux、mini-react-redux,去除了官方库的一些额外判断以及错误处理。经测试,在已实现的功能上完全可以替代官方库正确运行。注:本项目仅供学习参考使用,完整源码在 github
      本系列文章是对mini-redux、mini-react-redux的一些源码分析,该文章为第一篇,主要介绍createStore函数的实现。
    目录结构如下:

    image.png
    首先介绍一下mini-redux的入口文件index.js
    import createStore from './createStore';
    import bindActionCreators from './bindActionCreators';
    import applyMiddleware from './applyMiddleware';
    import compose from './compose';
    import combineReducers from './combineReducers'
    
    export { createStore, bindActionCreators, applyMiddleware, compose, combineReducers };
    
    

    redux最核心的概念便是store,下面是createStore的精简版实现,具体分析都有注释

    /* createStore.js */
    
    //  因为第二个参数和第三个参数可选,所以需要做一些前置判断
    export default function createStore(reducer, preloadedState, enhancer) {
      // 如果reducer不是函数类型,报错
      if (typeof reducer !== 'function') {
        throw new Error('Expected the reducer to be a function.');
      }
    
      // 如果第二个参数类型为function,则需要判断是否传入了第三个参数
      if (typeof preloadedState === 'function') {
        if (typeof enhancer !== 'undefined') {
          // 如果传入了第三个参数,则报错,因为此处第二个参数preloadedState被认为是函数类型,不合理
          throw new Error('Expected the preloadedState not to be a function.');
        }
    
        // 如果只传入了两个值且第二个参数类型为function,则将第二个参数的值赋给enhancer,preloadedState置为undefined
        enhancer = preloadedState;
        preloadedState = undefined;
      }
    
      // 如果enhancer非空,判断是否为函数类型
      if (typeof enhancer !== 'undefined') {
        if (typeof enhancer !== 'function') {
          throw new Error('Expected the enhancer to be a function.');
        }
    
        // 如果enhancer存在且类型正确,则执行enhancer并返回结果作为store。具体实现需要配合后面的applyMiddleware进行理解
        return enhancer(createStore)(reducer, preloadedState);
      }
    
      // 声明单一的state tree、监听器数组
      let currentState = preloadedState;
      const currentListeners = [];
      
      // 获取状态树
      function getState() {
        return currentState;
      }
      
      // 订阅事件
      function subscribe(listener) {
        if (typeof listener !== 'function') {
          throw new Error('Expected the listener to be a function.');
        }
        currentListeners.push(listener);
    
        // 这里应当返回一个函数,当它执行时取消该listener的监听
        return function unsubscribe() {
          const index = currentListeners.indexOf(listener);
          currentListeners.splice(index, 1);
        };
      }
      
      // dispatch的实现
      function dispatch(action) {
        if (typeof action !== 'object') {
          throw new Error('Actions must be plain objects.');
        }
        if (typeof action.type === 'undefined') {
          throw new Error('Actions may not have an undefined "type" property.');
        }
        
        // 根据reducer执行的结果更新状态树
        currentState = reducer(currentState, action);
        // 遍历监听器数组,执行每个listener函数
        currentListeners.forEach(listener => listener());
    
        return action;
      }
    
      // 生成store时,会默认派发一个初始化的action,用来初始化状态树。注意:这里的type不能与其它重名
      dispatch({ type: '@@redux/INIT' });
      
      // 返回一个具有getState、subscribe、dispatch方法的对象,即store
      return {
        getState,
        subscribe,
        dispatch
      };
    }
    
    
    相关文章

    mini-redux系列之一:createStore
    mini-redux系列之二:applyMiddleware
    mini-redux系列之三:combineReducers
    mini-redux系列之四:bindActionCreators
    mini-react-redux系列之一:Provider
    mini-react-redux系列之二:connect
    redux-thunk以及自定义redux中间件

    相关文章

      网友评论

        本文标题:mini-redux系列之一:createStore

        本文链接:https://www.haomeiwen.com/subject/ebpqdftx.html