/**
* createStore(reducer,preloadedState预存储状态,enhancer对store功能进行增强)
* {
*getState,dispatch,subscribe
* }
*/function createStore(reducer, preloadedState, enhancer) {
// 9,约束reducer参数类型
if (typeof reducer !== "function")
throw new Error("reducer must be a function");
// 12判断enchancer是否传递,是否是一个函数
if (typeof enhancer !== "undefined") {
if (typeof enhancer !== "function") {
throw new Error("enhancer must be a function");
}
// redux中调用,传入createStore 并返回一个函数,返回reducer, preloadedState
return enhancer(createStore)(reducer, preloadedState);
}// 1,sotre对象中存储的状态
var currentState = preloadedState;
// 6,存放订阅者函数
var currentListeners = [];
//2,获取状态
function getState() {
return currentState;
}
// 3用于触发action的方法
function dispatch(action) {
// 10,判断action是否是一个对象
if (!isPlainObject(action)) throw new Error("action必须是一个对象");
// 11,判断action中的type属性是否存在
if (typeof action.type === "undefined")
throw new Error("action对象中必须有type属性");
currentState = reducer(currentState, action);
// 根据当前状态和action处理返回新的状态
// 7循环数组调用订阅者
for (let i = 0;
i < currentListeners.length;
i++) {
// 获取订阅者
var listener = currentListeners[i];
// 调用订阅者
listener();
}
}// 5,订阅状态
function subscribe(listener) {
currentListeners.push(listener);
}//8 返回
return {
getState,
dispatch,
subscribe,
};
}// 4
// store.subscribe(() => {});
// 判断参数是否是对象类型
// 判断对象的当前原型对象是否和顶层原型对象相同
function isPlainObject(obj) {
// 排除基本数据类型和null
if (typeof obj !== "object" || obj === null) return false;
// 区分数组和对象 原型对象对比的方式
var proto = obj;
// 获取最顶层的原型对象
while (Object.getPrototypeOf(proto) !== null) {
proto = Object.getPrototypeOf(proto);
}
return Object.getPrototypeOf(obj) === proto;
// 返回true就是对象
}function applyMiddleware(...middlewares) {
return function (createStore) {
return function (reducer, preloadedState) {
// 创建store,拿到store,给中间件传参
var store = createStore(reducer, preloadedState);
// 阉割版的 store
var middlewareAPI = {
getState: store.getState,
dispatch: store.dispatch,
};
// 调用中间件的第一层函数 传递阉割版的store对象,返回中间件函数内的里面两层函数
var chain = middlewares.map((middleware) => middleware(middlewareAPI));
//中间件第二层参数传参,第三层就是dispath
var dispatch = compose(...chain)(store.dispatch);
// 返回一个增强版的store
return {
...store,
dispatch,
};
};
};
}function compose() {
var funcs = [...arguments];
console.log(funcs);
// 因为函数嵌套问题,执行顺序虽然是logger再thunk,为了保证顺序,要倒叙数组,先执行thunk第二层返回dispath,
return function (dispatch) {
for (var i = funcs.length - 1;
i >= 0;
i--) {
// 第一轮执行返回值返回是thunk里面的函数,他是logger需要的
dispatch = funcs[i](dispatch);
}
return dispatch;
};
}// bindActionCreators函数将action creator函数转换为能够触发action的函数
function bindActionCreators(actionCreators, dispatch) {
// 创建一个对象用于返回,返回值是一个对象
// function increment(){
//dispatch({type:'increment'})
// }
var boundActionCreators = {};
for (var key in actionCreators) {
// IIFE解决key变量不能保存的问题
(function (key) {
boundActionCreators[key] = function () {
dispatch(actionCreators[key]());
};
})(key);
// actionCreators[key]()拿到increment函数,执行,返回action对象
// dispatch(actionCreators[key]())dispatch action对象
}
return boundActionCreators;
}// combineReducers组合小的reducer成为大的reducer,返回一个reducer函数
function combineReducers(reducers) {
//检查reducer类型 它必须是函数
var reducerKeys = Object.keys(reducers);
for (var i = 0;
i < reducerKeys.length;
i++) {
var key = reducerKeys[i];
if (typeof reducers[key] !== "function")
throw new Error("reducer必须是函数");
}// 调用一个一个的小的reducer 将每一个小的reducer中返回的状态存储在一个新的大的对象中
return function (state, action) {
var nextState = {};
// 存储最新的状态
// 循环reducer拿到最新的状态
for (var i = 0;
i < reducerKeys.length;
i++) {
var key = reducerKeys[i];
var reducer = reducers[key];
var previousStateForKey = state[key];
nextState[key] = reducer(previousStateForKey, action);
}
console.log(nextState)
return nextState;
};
}
【redux核心代码初步实现】测试代码
Document - 锐客网
0