Redux源码分析(一)
Redux源码分析(createStore)
使用redux都快3年了,到现在也没认真去了解一下源码罪过啊,所以需要对它进行一些分析和学习,一方面能更好的去使用它,另一方面也学习一下该框架的设计思路,首先我们看到 redux/src/index.js 文件
export {createStore,combineReducers,bindActionCreators,applyMiddleware,compose,__DO_NOT_USE__ActionTypes
}
复制代码
所以主要部分也就是上面几个函数,我们下面一点点去分析每一个功能点
createStore
其实该文件有着大量的注释了,大家可以先简单的看看代码中的注释了解一遍。 其实createStore就是返回了一个对象,这个对象只有几个方法而已,而我们常用的就是dispatch,subscribe,getState这三个了
* Creates a Redux store that holds the state tree.* The only way to change the data in the store is to call `dispatch()` on it.
复制代码
该函数的作用呢就是建立一个store(废话嘛),那么什么是store呢?我的理解 就是一个仓库,存着整个程序的状态,且只能有一个,就是用这一个store搞定项目中的全部状态,当然不论多大的项目,统统只有这一个,弄两个肯定不好使,并且只有一个路子去修改里面的数据,那么就是调用dispatch()
function createStore(reducer, preloadedState, enhancer)
复制代码
可以看到函数体主要三个参数,简单说下
- reducer:它是一个函数可以表达为:
(preState,action) => newState
就是说根据action和之前的状态,返回一个新的状态(这里的新是新构建,而不是修改过,这点切记) - preloadedState:字面理解即可,预先加载的状态,即初始状态
- enhancer:这个需要拿出篇幅来说了,增强剂,增强createStore
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {enhancer = preloadedStatepreloadedState = undefined}
复制代码
也容易理解,在只有两个参数的情况,并且第二个为funcion的时候,那么第二个参数就是enhancer了,交互一下参数位置
if (typeof enhancer !== 'undefined') {if (typeof enhancer !== 'function') {throw new Error('Expected the enhancer to be a function.')}return enhancer(createStore)(reducer, preloadedState)}
复制代码
对enchancer类型判断,可以看到enhancer就是将store传入,在内部处理之后再将store返回来,继续传入reducer和初始状态进行构建
let currentReducer = reducerlet currentState = preloadedStatelet currentListeners = []let nextListeners = currentListenerslet isDispatching = falsefunction ensureCanMutateNextListeners() {if (nextListeners === currentListeners) {nextListeners = currentListeners.slice()}}
复制代码
建立一些变量保存reducer,state,以及订阅器保存在nextListeners中,ensureCanMutateNextListeners相当于每次对当前的订阅器进行备份,因为每次订阅一个listener的时候都是对nextListeners数组进行添加
function subscribe(listener) {if (typeof listener !== 'function') {throw new Error('Expected the listener to be a function.')}if (isDispatching) {throw new Error('You may not call store.subscribe() while the reducer is executing. ' +'If you would like to be notified after the store has been updated, subscribe from a ' +'component and invoke store.getState() in the callback to access the latest state. ' +'See https://redux.js.org/api-reference/store#subscribe(listener) for more details.')}let isSubscribed = trueensureCanMutateNextListeners()nextListeners.push(listener)return function unsubscribe() {if (!isSubscribed) {return}if (isDispatching) {throw new Error('You may not unsubscribe from a store listener while the reducer is executing. ' +'See https://redux.js.org/api-reference/store#subscribe(listener) for more details.')}isSubscribed = falseensureCanMutateNextListeners()const index = nextListeners.indexOf(listener)nextListeners.splice(index, 1)}}
复制代码
订阅器,注册监听函数,每一个listener都是一个func,并且返回了一个取消注册监听的函数unScribe,用于删除listener,其实就是将一个个的函数添加到数组中,之后每次在store发生变化的时候(其实也就是调用dispatch的时候)就会触发它~
function dispatch(action) {if (!isPlainObject(action)) {throw new Error('Actions must be plain objects. ' +'Use custom middleware for async actions.')}if (typeof action.type === 'undefined') {throw new Error('Actions may not have an undefined "type" property. ' +'Have you misspelled a constant?')}if (isDispatching) {throw new Error('Reducers may not dispatch actions.')}try {isDispatching = truecurrentState = currentReducer(currentState, action)} finally {isDispatching = false}const listeners = (currentListeners = nextListeners)for (let i = 0; i < listeners.length; i++) {const listener = listeners[i]listener()}return action}
复制代码
上面呢就是这里比较重要的dispatch函数了,其实非常简单,主要就是它:
currentState = currentReducer(currentState, action)
复制代码
将当前的全部状态和action传入reducer,得到新的state,这样就完成了state的状态更新了,之后再去遍历全部的listeners,从而在各个listeners的内部去更新view,完成整个流程(返回值其实还是这个action对象),其实以上内容和三个函数应该是redux的核心内容了,下面用一种简单的总结来表达一下store(借鉴的阮一峰的)
const createStore = (reducer) => {let state;let listeners = [];const getState = () => state;const dispatch = (action) => {state = reducer(state, action);listeners.forEach(listener => listener());};const subscribe = (listener) => {listeners.push(listener);return () => {listeners = listeners.filter(l => l !== listener);}};dispatch({});return { getState, dispatch, subscribe };
};
复制代码
而该文件还有两个函数分别是
function replaceReducer(nextReducer)
function observable()
复制代码
第一个很明显替换整个reducer用,在一些热加载场景应该会用到 而第二个暂时还不太理解作者意图,用观察者替换订阅发布吗?暂时先不去想 以上就是整个createStore的源码分析~
更多内容与讨论可以参考我的github.com/jinjiaxing/…
转载于:https://juejin.im/post/5cb946e4f265da038c020f2f
Redux源码分析(一)相关推荐
- redux源码分析之一:createStore.js
欢迎关注redux源码分析系列文章: redux源码分析之一:createStore.js redux源码分析之二:combineReducers.js redux源码分析之三:bindActionC ...
- redux源码分析之二:combineReducers.js
欢迎关注redux源码分析系列文章: redux源码分析之一:createStore.js redux源码分析之二:combineReducers.js redux源码分析之三:bindActionC ...
- Redux源码分析--Enhancer
Redux源码分析: Redux源码分析--Middleware(1) Redux源码分析--Middleware(2) Redux源码分析--Enhancer Redux源码分析--createSt ...
- redux middleware 源码分析
原文链接 middleware 的由来 在业务中需要打印每一个 action 信息来调试,又或者希望 dispatch 或 reducer 拥有异步请求的功能.面对这些场景时,一个个修改 dispat ...
- koa源码分析-co模块以及thunk
Thunk以及CO模块 co4.0之前都是返回的thunk函数 之后的都是返回promise thunk thunk:在 JavaScript 语言中,Thunk 函数替换的是将多参数函数,替换成单参 ...
- Vuex 2.0 源码分析
作者:滴滴公共前端团队 - 黄轶 大家好,我叫黄轶,来自滴滴公共前端团队,我们团队最近写了一本书 --<Vue.js 权威指南>,内容丰富,由浅入深.不过有一些同学反馈说缺少 Vuex 的 ...
- 学习 redux 源码整体架构,深入理解 redux 及其中间件原理
如果觉得内容不错,可以设为星标置顶我的公众号 1. 前言 你好,我是若川.这是学习源码整体架构系列第八篇.整体架构这词语好像有点大,姑且就算是源码整体结构吧,主要就是学习是代码整体结构,不深究其他不是 ...
- 【源码分析】redux-thunk
前言 前面学习redux时,学到了applyMiddleware云里雾里,所以这次学习一下redux-thunk的源码,希望有助于深入理解applyMiddleware的源码实现. redux-thu ...
- react-redux源码分析及实现原型(下)
上一次我们讲解了Provider.connect.selectorFactory.这次主要分析 connectAdvanced 这个核心API. react-redux源码分析及实现原型_上 conn ...
最新文章
- 张一鸣宣布卸任字节CEO!网友:完不成OKR被优化了!
- 常用的异常检测算法有哪些?
- oracle查询一个字符串所在表
- 深入理解定位父级offsetParent及偏移大小
- vue中怎么清空tab选项卡的缓存_vue Tab切换以及缓存页面处理的几种方式
- jdk官网历史版本下载Oracle账号密码
- STM32 电机教程 8 - 步进电机开环电流控制
- Linux下命令行安装weblogic10.3.6
- WebTable之ChildItem方法应用
- Perform the Combo CodeForces - 1311C(字符串反转+树状数组)
- 线程并发库和线程池的作用_线程和并发介绍
- as_hash ruby_Ruby中带有示例的Hash.each_pair方法
- 1.5 编程基础之循环控制 09 奇数求和
- PHP内核通用网站后台权限管理系统源码
- HBuilderX是什么
- jquery的validate表单验证表单注册插件
- [转]word 转换成pdf
- 如何设置Idea字体颜色
- php云erp进销存v8手机端,PHP仿金蝶云ERP进销存V8网络多仓版源码
- 证券机构分析师研报靠谱么?关于波司登沽空与买入报告
热门文章
- 苹果广告背景音乐大全【转】
- 红杉资源出售麦考林29%股份套现1亿美元
- 总结:Sharepoint2010 Client Object Model -- Silverlight Client
- Effective C# Item45 : 优先选择强异常安全保证
- bq4050读固件_stm32f767 实现模拟SMBUS驱动bq4050
- Java Web 程序设计----基于SSM框架(正在更新中)
- 安装 | cmd(命令提示符)窗口下使用conda安装TensorFlow
- C++练习 | C++中Vector的使用
- python如何判断字符串是否包含某些汉字_Python如何判断一个字符串是否包含指定子字符串...
- 易语言单窗口单ip软件源码_好人多窗口同步器:多台电脑同步视频演示