Redux源码解读

Redux 已经历了几个年头,很多 React 技术栈开发者选用它,我也是其中一员。期间看过数次源码,从最开始为了弄清楚某一部分运行方式来解决一些 Bug,到后来看源码解答我的一些假设性疑问,到最后想揭开它的面纱获得更多指导。在这个过程中我逐渐对 Redux 有了更多认识和收获,因此也决定写下这篇文章来和更多开发者一起交流。本文主要是赏析源码实现技巧,从源码层面介绍 Redux 使用中需要注意的地方。

用法简述

Redux 可以解耦 React(View层)与数据管理和对数据的操作,保持 React(层)的纯净,使职责划分清晰。同时降低了 React 数据传递难度与不可控性。它还提供可预测化的状态管理。Redux 采用了中间件机制,既保证了自身的最少代码量,又增加了可扩展性。下图为 Redux 的工作流程图。

01_workflow

工作流程

View 层通过 dispatch 方法发出 action,通知 store 用户有新操作。

store 收到通知会将处理权利交给 reducer,并传递给 reducer 两个参数:previousState 和 action,而 reducer 函数正是由你编写。

reducer 针对收到的用户操作(action)进行对应的数据处理,最后将处理完生成的新数据返回给 store。

store 收到新数据会通知 View 进行更新。

细节梳理

action 和 actionCreator 只是两种写法,actionCreator 允许用户编写的 action 中携带的数据是个变量,因此更通用。

dispatch 方法使用了中间件机制,增强了 dispatch 功能,如在每次 dispatch 时打印日志。

当用一个 reducer 来处理整个项目的所有 action 操作过于复杂时,可借助 combineReducers 分开处理。

state 是 store 在当前状态生成的数据对象。

走进源码

先看下文件目录,各文件的作用已在下图中标出。除内部工具函数外,本文会按照目录中的模块逐个梳理。同时,为保证文中能尽量多的留下一些干货,不去逐行梳理源码,会着重讲解结论和梳理代码常用技巧。

02_files

Index

作为入口文件,抛出了 Redux 可以使用的全部 API(见下图)。可以看到,每个 API 对应目录中一个文件。其中 __DO_NOT_USE__ActionTypes 是内部使用的 actionTypes,是随机生成的,自定义的 actionType 基本不会和这个冲突,因此这个 API 一般是用来做判断的。

03_indexexport

代码技巧

这里用到一个常用来判断代码混淆的技巧,通过定义一个空函数,随后判断这个空函数的 name 是否改变来确定代码是否进行了混淆。

CreateStore

这是 Redux 最核心的一个 API。有多核心?它覆盖了 Redux 的整个工作流程(见下图),如果你想自己实现一个简单的 Redux,看这个 API 就足够了!

05_createstoreflow

createStore 用来生成 store,该方法的签名为 ( reducer, preloadedState?, enhancer? ) => {dispatch, subscribe, getState, replaceReducer, [$observable]}。下面分析参数和返回值用法以及在工作流中的作用。

reducer参数: 是提供给用户实现根据发出的 action 更新 state 的函数,根据源码中调用方式(见下图)可知其签名为 ( previousState, action ) => newState,在工作流中注册了更新数据的函数等待被调用。

enhancer参数: 即 applyMiddleware() 返回的函数,createStore 方法中,有没有 enhancer 参数直接决定后面会走向哪里(见下图),但是不必恐慌,这只是为了提供给用户更多用法,即使这里 return 出去了,走一圈流程后,createStore 还是会返回上述签名中的内容,提供的更多用法会在 applyMiddleware 中说到。

07_enhancer

store.subscribe方法: 注册监听事件,并返回了取消监听的方法:( listener ) => unsubscribe,等待数据更新后被调用,在工作流中用来注册根据 state 变化来更新 View 的事件。

store.getState方法: 获取当前 state 数据对象,签名为 () => currentState。

store.replaceReducer方法: 用来更新 reducer 参数传入的函数,签名为 ( nextReducer ) => undefined。

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

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