redux源码解读(二)
之前,已经写过一篇redux源码解读(一),主要分析了 redux
的核心思想,并用100多行代码实现一个简单的 redux
。但是,那个实现还不具备合并 reducer
和添加 middleware
的功能。
今天我们一起来看看合并 reducer
(即 combineReducers
) 的原理和实现。
在分析原理之前,先来看看combineReducers
的用法:
import { createStore, combineReducers } from 'redux';
const addScore = (state, action) => {};
const deleteScore = (state, action) => {};
const rootReducer = combineReducers({addStore, deleteScore});
const store = createStore(rootReducer);
从上面的例子可以看出,combineReducers
接收的参数类型是一个原生对象,其中这个对象的每个键值都是一个 reducer
纯函数。另外,因为 combineReducer()
返回的结果可以传递给createStore
作为参数,可以推出它返回的结果也是一个 reducer
函数。
了解了 combineReducer
用法之后 ,那开始一步一步的用代码来实现其功能吧。
首先,需要先声明 combineReducers
的参数,然后判断传进来的参数是不是原生对象类型( plain object
),如果不是,则抛出异常,如果是,则需要获取该对象的所有属性(key)并存放到变量 reducerKeys
里面,然后对这些key进行遍历,过滤掉那些不是函数的值,并将结果放到 finalReducerKeys
里面。代码如下:
export default function combineReducers(reducers) {
// 判断参数reducers是否为对象
if(Object.prototype.toString.call(reducer) !== '[object Object]') {
throw new Error('combineReducers expected plain object params');
}
const reducerKeys = Object.keys(reducers);
let finalReducerKeys = [];
// 过滤掉value不是Function类型的键名,然后将结果放到fianlReducerKeys里面
reducerKeys.forEach((key, i) => {
if(typeof reducers[key] === 'function') {
finalReducerKeys.push(key);
}
});
}
前面已经提到过了 combineReducers
返回的结果是一个纯函数。那这个返回的函数需要处理些什么逻辑呢?因为他合并了其他的 reducers
,所以需要遍历这些 reducer
并执行他们。然后,并对比一下执行 reducer
之后的数据有没有变化 ,如果有变化则返回新的 state
, 否则直接返回之前的 state
。代码如下:
export default function combineReducers(reducers) {
// 省略和前面相同的部分
// 返回一个新的、经过组合的reducer函数
return function(state = {}, action) {
let hasChanged = false;
const nextState = {};
// 遍历finalReducerKeys,并调用对应的reducer。
finalReducerKeys.forEach((key, i) => {
const stateForKey = state[key];
const nextStateForKey = reducers[key](stateForKey, action);
nextState[key] = nextStateForKey;
// 如果前后状态不一样,则hasChanged设为true
if(stateForKey !== nextStateForKey) {
hasChanged = true;
}
});
// 如果有变化,则返回新的state,否则返回旧的
return hasChanged ? nextState : state;
}
}
OK,《redux
源码解读(二)》就写到这里,今天周五啦,祝大家周末愉快哈!如果对 combineReducer
还有不明白的地方,欢迎留言讨论哈。另外,可能有些地方我分析得不到位的,建议到我的github去下载代码自己再好好研究一下。重要的事情说三遍:代码在这里下载! 代码在这里下载! 代码在这里下载!
posted on 2018-08-03 20:03 ChessZhang 阅读(502) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?