We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
根据示例,可以看出来,我们首先是定义许多actions,并且分别定义了两个reducer函数,然后通过combineReducers将两个reducer合并在一起,然后做为createStore的参数传入,并执行。 我看网上其他人的解析都是先分析createStore,但是我觉得应该从combineReducers开始。
重要的两行代码是:
import { combineReducers } from 'redux' export default combineReducers({ todos, visibilityFilter })
我们根据这两行代码去找源码 我们找到了源码,原来就是这个combineReducers函数。我们看一下这个函数做了什么事情。(教大家一个小技巧,我们在看源码的时候,为了防止很多细节的代码,对主干代码的干扰,我们可以将大部分代码都合起来,需要看的时候再打开。)现在我们看到,combineReducers接受一个叫reducers的参数,返回一个闭包函数combination。 那么在返回这个combination函数之前,那一大坨代码干了什么事情呢?现在可以打开代码了,我们来看一下主要内容。
代码1部分,整个部分其实是为了生成一个finalReducers,让闭包使用。我们在使用redux的时候,单个reducer(todos, visibilityFilter)都应该定义成Function。这部分代码就是做了判断,看看这些单个reducer函数是不是undefined或是不是function,只有是function的才能幸运的进入finalReducers这个变量。 代码2部分大体就是一些数据格式的判断,有问题会报错。我没细看不影响大局。 好了我们再来看一遍redux官网给出的使用示例: 在reducers/index.js文件中,输出的其实就是combination闭包函数
export default combineReducers({ todos, visibilityFilter })
然后在index.js文件中,将combination函数起个名字rootReducer传入了createStore里。
import rootReducer from './reducers' const store = createStore(rootReducer)
好。那么我们可以开始分析createStore了
我们还是把细节代码合上,只看主干
先看官网是如何使用applyMiddleware的。
const logger = store => next => action => { console.log('dispatching', action) let result = next(action) console.log('next state', store.getState()) return result } const crashReporter = store => next => action => { try { return next(action) } catch (err) { console.error('Caught an exception!', err) Raven.captureException(err, { extra: { action, state: store.getState() } }) throw err } } import { createStore, combineReducers, applyMiddleware } from 'redux' const todoApp = combineReducers(reducers) const store = createStore( todoApp, // applyMiddleware() tells createStore() how to handle middleware applyMiddleware(logger, crashReporter) )
可以看到,定义了两个插件logger,和crashReporter。做为applyMiddleware的参数传入并执行了applyMiddleware函数。把执行过后的结果传入了createStore做为第2个参数 执行applyMiddleware后会return一个函数。也就是说传入createStore的是一个function。 符合途中黄色标记的if逻辑。那么传入的函数在createStore中叫做enhancer。 之后会走到执行逻辑中。 可以看到,先把createStore传入执行一下,返回一个函数,然后又把reducer和preloadedState(如果有的话)传入执行。 第1步,还是先执行createStore生成一个store(我们上面已经分析过了) 第2步,执行每一个middleware函数,都会返回一个函数,组成数组chain。 第3步,chain传入compose函数,生成函数执行链。然后把参数dispatch传入,并且执行那个函数执行链。 最终,返回store和dispatch。此时的dispatch是改造后的,不是原来那个了。
神奇的compose函数,生成了函数执行链。仔细看下是怎么生成的
一般情况下我们能在代码里直接用dispatch。但是redux还是提供了bindActionCreators。能让我们少写几个字的代码。 我们可以把actionCreators函数们组成的对象传入bindActionCreators。bindActionCreators做的就是生成一个新的对象boundActionCreators并return出去。boundActionCreators对象的key就是传入的actionCreator函数的名字,值就是新的函数function() {return dispatch(actionCreator.apply(this, arguments))}这样我们就不必显式的写那么多dispatch了哈哈。感觉还是很有用滴
The text was updated successfully, but these errors were encountered:
中间件机制关键代码实现
let funcs = [ (next)=>(action)=>{console.log(1);next(action);console.log(2)}, (next)=>(action)=>{console.log(3);next(action);console.log(4)} ] let dispatch = (action)=>{ console.log(action) } const compose = function(funcs){ return funcs.reduce((a,b)=>{ return (dispatch)=>a(b(dispatch)) }) } dispatch = compose(funcs)(dispatch) dispatch('我派发了action')
Sorry, something went wrong.
~~
No branches or pull requests
redux源码解析
redux源码地址
redux主要代码的目录结构
接下来我们按照redux的官方网站提供的redux使用示例,来一步步看下每个函数的作用
根据示例,可以看出来,我们首先是定义许多actions,并且分别定义了两个reducer函数,然后通过combineReducers将两个reducer合并在一起,然后做为createStore的参数传入,并执行。
我看网上其他人的解析都是先分析createStore,但是我觉得应该从combineReducers开始。
combineReducers
重要的两行代码是:
我们根据这两行代码去找源码
我们找到了源码,原来就是这个combineReducers函数。我们看一下这个函数做了什么事情。(教大家一个小技巧,我们在看源码的时候,为了防止很多细节的代码,对主干代码的干扰,我们可以将大部分代码都合起来,需要看的时候再打开。)现在我们看到,combineReducers接受一个叫reducers的参数,返回一个闭包函数combination。
那么在返回这个combination函数之前,那一大坨代码干了什么事情呢?现在可以打开代码了,我们来看一下主要内容。
代码1部分,整个部分其实是为了生成一个finalReducers,让闭包使用。我们在使用redux的时候,单个reducer(todos, visibilityFilter)都应该定义成Function。这部分代码就是做了判断,看看这些单个reducer函数是不是undefined或是不是function,只有是function的才能幸运的进入finalReducers这个变量。
代码2部分大体就是一些数据格式的判断,有问题会报错。我没细看不影响大局。
好了我们再来看一遍redux官网给出的使用示例:
在reducers/index.js文件中,输出的其实就是combination闭包函数
然后在index.js文件中,将combination函数起个名字rootReducer传入了createStore里。
好。那么我们可以开始分析createStore了
createStore
我们还是把细节代码合上,只看主干
接收action做为参数,返回action。中间有一句代码比较关键currentState = currentReducer(currentState, action)。其实是执行了currentReducer函数,这个函数是谁呢?其实就是之前combineReducers返回的闭包函数combination。让我们看一下详细的定义
这个函数接收state和action,返回新的state。我们自己定义的actions里面并没有ActionTypes.INIT这个type,那为什么这里要执行呢?我自己跑了一个例子,从头debug了一次,发现这是要初始化state。生成了原始的store。这个过程是必须的。
applyMiddleware
先看官网是如何使用applyMiddleware的。
可以看到,定义了两个插件logger,和crashReporter。做为applyMiddleware的参数传入并执行了applyMiddleware函数。把执行过后的结果传入了createStore做为第2个参数
执行applyMiddleware后会return一个函数。也就是说传入createStore的是一个function。
符合途中黄色标记的if逻辑。那么传入的函数在createStore中叫做enhancer。
之后会走到执行逻辑中。
可以看到,先把createStore传入执行一下,返回一个函数,然后又把reducer和preloadedState(如果有的话)传入执行。
第1步,还是先执行createStore生成一个store(我们上面已经分析过了)
第2步,执行每一个middleware函数,都会返回一个函数,组成数组chain。
第3步,chain传入compose函数,生成函数执行链。然后把参数dispatch传入,并且执行那个函数执行链。
最终,返回store和dispatch。此时的dispatch是改造后的,不是原来那个了。
compose
神奇的compose函数,生成了函数执行链。仔细看下是怎么生成的
bindActionCreators
一般情况下我们能在代码里直接用dispatch。但是redux还是提供了bindActionCreators。能让我们少写几个字的代码。
我们可以把actionCreators函数们组成的对象传入bindActionCreators。bindActionCreators做的就是生成一个新的对象boundActionCreators并return出去。boundActionCreators对象的key就是传入的actionCreator函数的名字,值就是新的函数function() {return dispatch(actionCreator.apply(this, arguments))}这样我们就不必显式的写那么多dispatch了哈哈。感觉还是很有用滴
The text was updated successfully, but these errors were encountered: