You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
function isCrushed() {}
if (
process.env.NODE_ENV !== 'production' &&
typeof isCrushed.name === 'string' &&
isCrushed.name !== 'isCrushed'
) {
warning(
'You are currently using minified code outside of NODE_ENV === \'production\'. ' +
'This means that you are running a slower development build of Redux. ' +
'You can use loose-envify (https://github.com/zertosh/loose-envify) for browserify ' +
'or DefinePlugin for webpack (http://stackoverflow.com/questions/30030031) ' +
'to ensure you have the correct code for your production build.'
)
}
export default function createStore(reducer, preloadedState, enhancer) {
}
getState函数:
let currentState = preloadedState
function getState() {
return currentState
}
getState函数比较简单,类似于一个get的方法,返回currentState的值
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
}
function subscribe(listener) {
if (typeof listener !== 'function') {
throw new Error('Expected listener to be a function.')
}
let isSubscribed = true
ensureCanMutateNextListeners()
nextListeners.push(listener)
return function unsubscribe() {
if (!isSubscribed) {
return
}
isSubscribed = false
ensureCanMutateNextListeners()
const index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1)
}
}
function replaceReducer(nextReducer) {
if (typeof nextReducer !== 'function') {
throw new Error('Expected the nextReducer to be a function.')
}
currentReducer = nextReducer
dispatch({ type: ActionTypes.INIT })
}
简要介绍:用了一段时间redux,今天看了一下redux的源码,大致整理了心得如下。
1、什么是redux,这里就不做介绍,如想了解可以移步 ReadMe.redux,整体redux的代码只有800行,src下面分为一下几个部分。
applyMiddleware.js
bindActionCreators.js
combineReducers.js
compose.js
createStore.js
index.js
首先我们来看index.js主js的内容,很简单,就是引入和模块和抛出模块,这里有一句提醒内容,如果是production生产环境并且js已经被压缩,会输出warning信息
注: isCrushed.name 函数名.name是一个es6的属性,返回函数的名称。
除了index.js外,我们接下去从redux实现的接口,来深度分析一下Redux的源码。
2、compose.js
我们首先从compose.js入手,首先redux贯穿始终的是函数式变成的思想,个人对于函数式编程的理解为:
首先是纯函数(相同的输入产生相同的输出)
在范畴论理,状态或者输出表示点,函数表示边,从点到点的转移可以看成运算符,函数也是一种运算符,因为运算符是纯净的,因此函数式编程中的函数也是纯净的
函数式编程中的函数,与变量等价,可以作为参数传递或者成为其他函数函数体里的一部分
因为是函数式编程,便于函数的组合,这里有一个curry和compose的组合过程
基础了解函数式编程之后,下面我们来看compose.js的源码:
这个compose其实很简单,传入的参数为函数数组,返回的为reduce从左到右合并后的新的函数。是一个类似于链式调用的过程。
来看:
这句特别重要,组合函数的这部非常重要,我们发现...args参数会依次的从右到左执行,比如将b(...args)的执行结果,传入a中作为参数继续执行。
3、applyMiddleware.js
applyMiddleware.js其实是基于compose.js来实现的
上述代码如果applyMiddleware(...Middleware)(createStore)这样调用,会生成一个新的createStore函数,用于创建新的createStore,新在哪里呢?就是链式的调用了所有的middleware:
来看上述的代码,chain是一个函数数组,是middleware({})执行后的返回函数的数组,compose(...chain)是链式的组合函数,这里的...args是初始时候的store.dispatch,当最右边的函数以store.dispatch为参数,执行后生成一个新的store.dispatch,又向外传递,因此middleware是从右到左执行的。
从上述的描述中,我们知道了middle的书写形式,如果以纯函数的形式,首先第一个参数应该是{getState:'',dispatch:''},第二个参数是store.dispatch,第三个参数应该是action,因此最基本形式的middleware应该是:
return ({ dispatch, getState }) => next => action => {
}
我们以redux-thunk为例,redux-thunk中间件是严格按照上述的形式,
代码只有13行:
这个中间件的功能其实很简单,也就是action如果是一个函数就选择执行这个函数,并且action函数执行的时候,会传入dispatch和getState.
4、createStore.js
createStore相对而言会较为的复杂,我们还是从接口出发。
(1) 首先看,createStore()函数的返回值store有哪些接口:
getState():返回当前的state树
dispatch(action):分发action,是改变state的唯一方法
subscribe(listener):添加一个监听器,当state变化的时候,执行监听器里面的函数。
unsubscribe(listener):subscribe的返回值,用于移除监听器
replaceReducer(nextReducer):替换store中当前的reducer
(2) 下面根据代码,依次来看,各个接口的实现情况。
首先明确createStore的形参,形参有3个,分别是reducer(处理函数),initState(初始化state),enhancer(一个高阶函数,可以改变store的接口)。
getState函数比较简单,类似于一个get的方法,返回currentState的值
dispatch也不复杂,去掉判断类型(因为action必须是对象)的部分,其实只有2步:
这就很显然易见了,就是执行currentReducer()传入当前的currentState和action,返回新的state,并且执行监听函数数组里面的所有函数。
监听函数也挺简单,就是一个简单的移入和移出,这是一个底层 API。多数情况下,你不会直接使用它,会使用一些 React(或其它库)的绑定。比如react-redux中的容器组件中的props改变会自动的更新(也算一个监听过程)。
这个函数就更加的简单了,replaceReducer是为了改变当前的reducer,因此只要将currentReducer赋值为形参即可。
5、combineReducers.js
最复杂的部分就是combineReducer.js了
示属性名,value是一个小的reduce函数:
其原理也很简单,state的属性名和reducer对象的key是相对的,因此也就是在所有的小的reduce函数中,传入相对的state[key],action,依次执行后得到一个新的newState,然后与state做比较,选择性返回。
6、bindActionCreators.js
这个一般比较少用,这里就不分析源码了,只简单的阐述功能,
bindActionCreators()把 action creators 转成拥有同名 keys 的对象,但使用 dispatch 把每个 action creator 包围起来,这样可以直接调用它们。
The text was updated successfully, but these errors were encountered: