写个结构清楚的东西好难啊,但我还是尽力为之努力吧。
之前把程墨那本《深入浅出React和Redux》前几章过了一遍,各章节例子也敲着跑通了,好像理解过程中也没什么很大障碍的样子,然后就大概觉得自己差不多懂了,想着应该可以简历上可以加一条熟悉react和redux啦。然后今天想着不去翻书完全自己动手再把todolist的例子敲出来然后自己再加点功能,发现把书上例子敲出来之后(还是得翻几下书),对于自己相加的功能,完全不知从何下手。于是我意识到,我大概把之前理解的东西都忘了,或者不客气说,根本从来都没有理解,所以,慢慢体会到做笔记的重要,所以这也是这篇笔记出生的原因。
我想我现在可能还不具备那种统筹全局的本领,只能先逐渐积累零散的知识,一点一点吃透。所以,对于什么flux,redux那些我暂时还不能深刻体会的设计思想以及相关背景什么的,我就不强行去copy别人的介绍了,直接上重点。
容器组件和展示组件
这两个组件是什么我就不介绍了,先从一个问题引出我想说的:容器组件是怎样驱动展示组件更新的?
我在之前一篇笔记上说了组件更新的方式一个是自身调用this.state
主动更新,另一个是由父组件的re-render而被动更新,这里问的是容器组件驱动,意味主动权在在容器组件上,那肯定就是第二种,容器组件的re-render驱动展示组件更新,进而更新对应的UI内容。
那继续下一个问题:容器组件又是怎么更新的呢?
还是那两种方式,自我调用this.setState
或者父组件re-render,容器组件已经是父组件了,它的更新还要继续依赖它外层的父组件,但是我们知道容器组件是根据store里的state tree来更新,所以应该不是那种情况;那这样的话只能是其自身this.setState
来更新了。嗯,这一切都很正常啊,这么理所应当的事情还要啰嗦这么多吗?是啊,我当时看书的时候应该也是这么想的。但是就在我今天发现自己想要给todolist加个功能都动不了手的时候,我想肯定是这两个组件的作用我都没搞明白,所以我就通过google 那个react的工具看了下容器组件里都有什么,然后我就发现,容器组件的state都是空的,

不对啊,不是说容器组件是通过
this.setState
来更新的吗,可是怎么state里面什么都没有啊,而且我又去看了下只用redux的实现,它的容器组件里this.state
都有值。然后我想是不是还有别的什么方式驱动更新啊,或着我前面的猜测是错的,于是我网上搜相关的文章啊,符合条件的文章每一篇都明确告诉我容器组件是通过this.state
更新的,有几篇同时说容器组件是有state的,并且贴出相关源码并分析原理:容器组件在componentDidMount
阶段subscribe(handleChange)
store的state tree的变化,变化时调用handleChange
,而handleChange
里处理的手段就是this.setState(newState)
,可是我看到的容器组件的this.state
明明明明明明就是空的呀,怎么办,难道我这样的菜鸡居然也要去看源码?虽然很自不量力,但是我怕不搞明白这个问题别的就继续不下去了,所以带着为什么容器组件的
this.state
是空的这个问题去忐忑的去翻源码了。从哪看呢?前面说了只用redux实现的话容器组件的
this.state
是有内容的(因为驱动容器组件更新的代码是需要自己手动去实现的,明确的用了this.setState
来更新),那reaxt-readux与redux不同的地方在哪?connect和provider,问题出现在前者看起来可能性更大一点,然后终于在一个名为'connectAdvanced.js'的文件里找到this.setState(dummyState)
这样的一条语句,而且这条语句在一个名叫onStateChange
这样的方法里,看起来我应该找对了,然后我搜了下关键字'dummyState',接下来看到的语句让我瞬间有种好像什么都明白了的感觉,对,那种一旦出现就会让你觉得什么问题都会解决的感觉。好吧,不啰嗦了,上语句:var dummyState = {}
。好了,原来容器组件根本就不需要维持自己的this.state
,它已经把state tree上的state都map给展示组件了,每次state tree变化的时候,它消让通知展示组件去re-render进行更新就行了,怎么通知?自己re-render一下就好了,这就是为什么容器组件的this.state
是个空对象的原因。其实从'dummyState'这个变量名称的意义应该就能猜到这么做的意义。
形容词
虚设
dummy, fake, nominal, mock
假的
dummy, supposititious, bum
之后为了更确认,我想改下这个dummyState
的值看容器组件的this.state
也会不会变成相应的值,可是我发现我不知道它加载的是哪个文件夹下的文件,没办发,去它package.json
里碰碰运气吧,找到这样的字段"main": "./lib/index.js"
,好,试着改下,运行,好像运气不错:

我就说那种感觉从来不骗人。这样,第一次与源码打交道的经历就很识趣地迅速结束了。嗯,有了第一次肯定又会有下次的,我还挺期待?明明看到那密密麻麻的代码就头皮发麻。
再回过头来总结下容器组件和父组件里都有什么,画了张图:

- 容器组件
里面除了需要用到context提供的store之外,什么也没有,也不需要,只用负责把state tree上的东西传到展示组件的props - 展示组件
功能如其名,展示,展示容器组件传过来的东西,给什么就展示什么;其props包含三部分:- 与state tree相关的props
这部分props会因为state tree对应部分的变化而变化,从而改变UI上对应的内容 - 用来dispatch action的props,这部分props通常是处理与用户交互的函数,改变state tree的状态,也即改变上面那部分props的变化,从而引起自身UI的更新
- 从容器组件传过来的props
这部分props是在容器组件实例化的时候从容器组件的props中传过来的,我猜想是不是可以用来实现多个相同组件同时出现时的差异化。
- 与state tree相关的props
好了,这部分内容就这些了。其实还有一部分的(这部分是前天拖着没写的),原以为能把两部分都写完,写这么点就花这么长时间,好难啊。
纸上得来终觉浅,绝知此事要躬行。越将想法付诸实践越能体会到这句的真理。
网友评论