内容简介:使用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使用及源码分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Node.js:来一打 C++ 扩展
死月 / 电子工业出版社 / 2018-6-1 / 109
Node.js 作为近几年新兴的一种编程运行时,托 V8 引擎的福,在作为后端服务时有比较高的运行效率,在很多场景下对于我们的日常开发足够用了。不过,它还为开发者开了一个使用C++ 开发 Node.js 原生扩展的口子,让开发者进行项目开发时有了更多的选择。 《Node.js:来一打 C++ 扩展》以 Chrome V8 的知识作为基础,配合 GYP 的一些内容,将教会大家如何使用 Node......一起来看看 《Node.js:来一打 C++ 扩展》 这本书的介绍吧!