Redux源码解读 (4)

Chrome 中:

写法 运行速度(ops/sec)
回调嵌套写法   56,919  
递归实现   44,346  
reduce 写法   47,450  
自定义 next   49,950  

Firfox 中:

写法 运行速度(ops/sec)
回调嵌套写法   10,660  
递归实现   8,411  
reduce 写法   8,411  
自定义 next   9,095  

Safari 中:

写法 运行速度(ops/sec)
回调嵌套写法   298,880  
递归实现   117,379  
reduce 写法   161,663  
自定义 next   220,944  
CombineReducers

该方法代码虽多但只做了一件事,就是允许你定义多个 reducer 函数然后帮你合并成一个,在工作流中的作用见下图。

16_combinereducersflow

既然是要合并 reducer,那么合并后的函数也要和 reducer 写法一致。因此:
comineReducers: (reducers) => (state, action) => newState
这里的 reducers 是一个对象,如 { a: reducer1, b: reducer2 }。不过一般都会让 key 和 value 的函数名一致,es6 语法即可写为 { reducer1, reducer2 },核心代码如下:

17_combinereducerscore

从图中可看到直接调用了 reducer,并未对生成数据做其他处理(这和 createStore 中调用 reducer 是一致的),同时 hasChange 只做了浅比较,这样一来我们编写的时候需要注意什么呢?浅比较又有什么好处呢?不妨接着看完使用注意。

使用注意

通过 combineReducers 合并会使生成的 state 对象树在顶层增加一层。

代码中有大量校验,其中就限制了编写的 reducer 不能返回 undefined,如果想清空数据返回 null,想还原数据返回原来的 state。

源码中 comineReducers 生成的 rootReducer 被执行的时候会依次执行每个 reducer。当 reducer 中有两个方法都处理了同一个 action,那么这两个处理方法都会被执行。为避免这这种不确定性可能导致的 bug,将所有 action.type 的字符串都统一定义在一个文件中是很有帮助的,当然这样做还有其他好处。

源码在进行 hashChange 判断时,对每个 reducer 生成的数据都是进行的浅比较,最后通过 hasChange 判断应返回 nextState 还是 state。因此如果 state 发生了变更,要保证 reducer 返回的 state 和原 state 没有引用关系,否则无法更新。另外这里用浅比较的好处是如果没有更改或者没有命中任何 action 处理方法返回原 state,这样可以避免更新提高性能。

BindActionCreators

该方法代码量少做的事情也简单,目的是优化 store.dispatch(actionCreator(data)) 这种调用方式,下图为优化前后使用姿势对比。

18_bindactioncreatorsapi

根据上面的对比很容易得出结论,这个方法只是将 store.dispatch 调用进行了封装,简化了调用写法,核心代码见下图:

19_bindactioncreatorscore

总结

本文围绕源码实现技巧和使用注意事项展开,希望尽可能给小伙伴们提供一些思想上的启发和开发上的帮助。阅读源码就像读一本好书,每次阅读都会有不同的收获。在这个过程中,我总结了自己的阅读源码的方法供大家参考。

准备一个使用源码的 demo,随时用来运行调试,大部分库也可以选用它本身提供的例子。

快速梳理清楚源码的结构及每部分功能的大致位置。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpyddp.html