内容简介:使用redux都快3年了,到现在也没认真去了解一下源码罪过啊,所以需要对它进行一些分析和学习,一方面能更好的去使用它,另一方面也学习一下该框架的设计思路,首先我们看到所以主要部分也就是上面几个函数,我们下面一点点去分析每一个功能点其实该文件有着大量的注释了,大家可以先简单的看看代码中的注释了解一遍。 其实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 = preloadedState preloadedState = 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 = reducer let currentState = preloadedState let currentListeners = [] let nextListeners = currentListeners let isDispatching = false function 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 = true ensureCanMutateNextListeners() 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 = false ensureCanMutateNextListeners() 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 = true currentState = 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/…
以上所述就是小编给大家介绍的《Redux源码分析(一)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 以太坊源码分析(36)ethdb源码分析
- [源码分析] kubelet源码分析(一)之 NewKubeletCommand
- libmodbus源码分析(3)从机(服务端)功能源码分析
- [源码分析] nfs-client-provisioner源码分析
- [源码分析] kubelet源码分析(三)之 Pod的创建
- Spring事务源码分析专题(一)JdbcTemplate使用及源码分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Fluent Python
Luciano Ramalho / O'Reilly Media / 2015-8-20 / USD 39.99
Learn how to write idiomatic, effective Python code by leveraging its best features. Python's simplicity quickly lets you become productive with it, but this often means you aren’t using everything th......一起来看看 《Fluent Python》 这本书的介绍吧!