Redux API 分解实现
createStore
const store = createStore(
countReducer,
applyMiddleware(thunk, logger, promise)
);从使用实例可以搭出函数框架
export default function createStore(reducer, enhancer) {
let currentState; // 选中的状态值,记录下方便获取
let currentListeners = []; // 选中的监听器,方便订阅和取消订阅
function getState() {}
function dispatch() {}
function subscribe() {}
return {
getState,
dispatch,
subscribe,
};
}然后依次实现
getState 比较简单 直接返回选中值即可
function getState() {
return currentState;
}dispatch 函数只是在 reducer 中找到对应的函数执行以后,进行对视图的通知更新
// add = () => {
// store.dispatch({ type: "ADD" });
// };
function dispatch(actions) {
//将reducer执行一遍,获取变化后的值
currentState = reducer(currentState, actions);
// 发布订阅模式 都是通过一个数组进行遍历通知视图进行更新
currentListeners.forEach((listener) => listener());
}订阅函数 subscribe 则是标准的发布订阅函数,记得返回一个取消订阅的函数
//订阅函数
function subscribe(fn) {
currentListeners.push(fn);
// 返回一个取消订阅函数
return () => (currentListeners = []);
}最后执行一次 dispatch 进行默认值的设定
dispatch({ type: "随机生成一段Type进行初始值设置" });applyMiddleware
顾名思义中间件,把 createStore 通过一轮 Middleware 增强一遍
if (enhancer) {
enhancer(createStore)(reducer);
}这样我们就可以搭出如下框架
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer) => {
let store = createStore(reducer);
// 这是原版的dispatch,这个dispatch只能接受plain object,不能处理异步、promise
let dispatch = store.dispatch;
return {
...store,
// 加强版的dispatch
dispatch,
};
};
}这里需要注意 ,我们传入了多个增强函数,需要一次执行增强同一个参数,like this
将参数向下传递,进行加强后,继续向下传递
function f1(arg) {
console.log("f1", arg);
return arg;
}
function f2(arg) {
console.log("f2", arg);
return arg;
}
function f3(arg) {
console.log("f3", arg);
return arg;
}
const res = f1(f2(f3("omg")));
console.log("res", res); //sy-log
// f3 omg
// f2 omg
// f1 omg
// res omg但是这么写不免繁琐,所以就有了
compose
![[高阶函数#compose#redux 版本 同步函数]]
也叫函数合成,执行顺序是越后面越内层,也就是越早执行
这样我们就可以开始使用中间件进行函数增强了
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer) => {
.....
const API = {
state: store.getState(),
dispatch: (actions, ...args) => store.dispatch(actions, ...args),
};
//将middlewares转化成 参数为 API 的函数数组
const middlewaresChain = middlewares.map((middleware) => middleware(API));
// 对 dispatch 进行增强
dispatch = compose(...middlewaresChain)(store.dispatch);
.....
};
}combineReducers
用法改变
<p>{store.getState()}</p>
=>
<p>{store.getState().home}</p>const store = createStore(
// combineReducers用法
combineReducers({home: countReducer}),
applyMiddleware(thunk, logger, promise)
);combineReducers 辅助函数的作用是
- 把一个由多个不同 reducer 函数作为 value 的 object,
- 合并成一个最终的 reducer 函数,然后就可以对这个 reducer 调用 createStore。
使用规则:
-
每个传入 combineReducers 的 reducer 都需满足以下规则:
-
所有未匹配到的 action,必须把它接收到的第一个参数也就是那个 state 原封不动返回。
-
永远不能返回 undefined。当过早 return 时非常容易犯这个错误,为了避免错误扩散,遇到这种情况时 combineReducers 会抛异常。
-
如果传入的 state 就是 undefined,一定要返回对应 reducer 的初始 state。根据上一条规则,初始 state 禁止使用 undefined。
使用 ES6 的默认参数值语法来设置初始 state 很容易,但你也可以手动检查第一个参数是否为 undefined。
实现:
export default function combineReducers(reducers) {
return function combination(state = {}, action) {
var hasChanged = false; // 做缓存的标记
var nextState = {};
// 循环reducer,如果是函数就进行执行
// 将执行完成的值,赋值给对象保存
for (let key in reducers) {
let reducer = reducers[key];
if (typeof reducer !== "function") {
break;
}
var previousStateForKey = state[key];
var nextStateForKey = reducer(previousStateForKey, action);
nextState[key] = nextStateForKey;
//判断值有没变化
hasChanged = hasChanged || nextStateForKey !== previousStateForKey;
}
//判断有没新增state
hasChanged =
hasChanged || Object.keys(nextState).length !== Object.keys(state).length;
return hasChanged ? nextState : state;
};
}redux 内部的 API 我们已经全部实现了。