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

首先介绍一下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中间件