理解Redux应用架构——(二)创建store的createStore

    “整个应用的 state被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个store 中。”这是Redux官方文档给出三大原则的第一条,着重强调了单一数据源这个概念其中,单一数据源的一个重要的前提,就是有唯一一个store,而这个store,正是被我们今天要讲的核心API——createStore创建的,至于我们担心数据过于庞大的问题,之前在概览中提到的API——combineReducers正是用来解决这个问题的。

createStore.js概览

   createStore可谓是整个Redux的灵魂。基本上Redux的核心功能已经全部被createStore以及createStore生成的store中,下面我们就来了解一下createStore究竟是怎么工作的,createStore的源码比较长,我们分两段贴出︿( ̄︶ ̄)︿:

createStore1

这段可以看到,createStore接受3个参数:reducer, preloadedState, enhancer。reducer我们接下来会具体介绍,这里不过多赘述,第二个参数是preloadedState,它是state的初始值,实际上他并不仅仅是扮演着一个initialState的角色,如果我们第二个参数是函数类型,createStore会认为你忽略了preloadedState而传入了一个enhancer,如果我们传入了一个enhancer,createStore会返回enhancer(createStore)(reducer, preloadedState)的调用结果,这是常见高阶函数的调用方式。在这个调用中enhancer接受createStore作为参数,对createStore的能力进行增强,并返回增强后的createStore。然后再将reducer和preloadedState作为参数传给增强后的createStore,最终得到生成的store。

createStore2

这段我们省略了dispatch,subscribe,getState,replaceReducer,[$$observable]: observable的代码,因为我们会在接下来去依次剖析他们,这里也可以看出,createStore的返回值是dispatch,subscribe,getState,replaceReducer,[$$observable]: observable,它们共同组成了一个store,实际上它本身只暴露出来四个方法dispatch,subscribe,getState,replaceReducer,而[$$observable]: observable是供Redux内部使用的,有兴趣的童鞋可以自己去研究(传送门),本文就不再赘述。稍后我们将会介绍这四个我们可以使用到的API。

1.action

这里插一个action,action代表的是用户的操作。redux规定action一定要包含一个type属性,且type属性也要唯一,相同的type,redux视为同一种操作,因为处理action的函数reducer只判断action中的type属性。

2. reducer

Redux中负责响应action并修改数据的角色就是reducer,reducer的本质实际上是一个函数,其函数签名为:reducer(previousState,action) => newState。可以看出,reducer 接受两个参数,previousState以及action函数返回的action对象,并返回最新的state,实际上reducer在处理previousState还需要一个特殊的非空判断,以下是一个Dome:

2

reducer 只是一个模式匹配的东西,真正处理数据的函数,一般是额外在别的地方写的(当然直接写在reducer中也没问题,只是不利于后期维护),在 reducer 中调用罢了。reducer 为什么叫 reducer 呢?因为 action 对象各种各样,每种对应某个 case ,但最后都汇总到 state 对象中,从多到一,这是一个减少( reduce )的过程,所以完成这个过程的函数叫 reducer。

3.getState

源码如下:

getState

可以看出,这里定义了4个本地变量:

    1、currentReducer:当前的reducer,支持用过store.replaceReducer方式动态替换reducer,为代码热替换提供了可能。

    2、currentState:应用当前的状态,默认为初始化状态。

    3、listeners:当前监听store的监听器

    4、isDispatching:某个action是否处于分发处理过程中。

4.subscribe

在getSate之后,我们又定义了subscribe:

subscribe

subscribe接收一个listener,它的作用是给store添加监听函数。nextListeners储存了整个监听函数列表。 subscribe的返回值是一个unsubscribe,是一个解绑函数,调用该解绑函数,会将已经添加的监听函数删除,该监听函数处于一个闭包之中,会一直存在,所以在解绑函数中能删除该监听函数。(由此可见redux源码设计的精巧,多处地方巧用闭包,精简了许多代码。)

你可能会奇怪,好像我们在Redux中并没有使用过subscribe方法,实际上React Redux 中的 connect方法隐式地帮我们完成了这个工作。

5.dispatch

   接下来,要说的是store非常核心的一个方法,也是我们在应用中最常使用的方法dispatch。他的源码如下:

dispatch

   首先,我们校验了action是否为一个原生js对象,接下来为我们校验了action对象是否包含了必要的type字段。再接下来,判断当前是否处于某个action分发过程中,这个检查主要是为了避免在reducer中分发action。

    在一系列检查完毕后,若均没有问题,将当前的状态和action传给当前reducer,用于生成新的state。在得到新的状态后,依次调用所有的监听器,通知状态变更。需要注意的是,我们在通知监听器变更发生时,并没有将最新的状态传给监听器。这是因为在监听器中我们可以直接调用store.getState()方法拿到最新的状态,最后,奖处理之后的action返回。

6.replaceReducer    

replaceReducer

replaceReducer是替换当前的reducer的函数,replaceReducer接受一个新的reducer,替换完成之后,会执行 dispatch({ type: ActionTypes.INIT }) ,用来初始化store的状态。官方举出了三种replaceReducer的使用场景,分别是:

   1、当你的程序要进行代码分割的时候

    2、当你要动态的加载不同的reducer的时候

    3、当你要实现一个实时reloading机制的时候

至此,这个至关重要的“灵魂”API——createStore已经基本介绍完了,到目前为止,我们都在一个清晰的同步数据流中跑动,但是实际开发过程中,这远远不能满足我们的需求,比如我要发送一个请求,等数据返回后再更新View怎么办?这就需要我们使用Redux middleware了,下一章,将为大家介绍Redux中间件middleware,这也是我本人非常喜欢的一块代码,代码之简洁,思维之精妙真的是很令人受教,敬请期待下一章~( ̄▽ ̄~)(~ ̄▽ ̄)~。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容