摘要:一种是子元素仍然是复杂对象,也就是说子元素还是组件,需要递归处理嵌套的子组件直到到达他们的内容层级。处理方式是根据的类型来判断的。在我们的列子中,组件组件有三个子元素,,和。现在我们要对元素内容进行更新,事实上,是替换它的内容。
接上文,
React流程图:
https://bogdan-lyashenko.gith...
更新方法基于子元素上的多个属性去处理子元素。这里会有几种场景,但是技术上来说主要是两种。一种是子元素仍然是‘复杂’对象,也就是说子元素还是React组件,React需要递归处理嵌套的子组件直到到达他们的内容层级。还有一种,就是子元素已经是内容层级里,内容就是字符串或者数字或者其他简单类型。
处理方式是根据nextProps.children的类型来判断的。在我们的列子中,组件
我们看下它是如何运作的。
在Examplication子元素的第一次迭代期间,子元素的类型不是内容,所以需要进入到‘复杂’组件的处理逻辑。我们遍历所有的子元素,按之前处理它们父元素的过了处理它们。顺便提下,验证shouldUpdateReactComponent的代码块会令人有点疑惑,表面上看起来这个是用来检测是否需要更新,但是实际上,它除了检测更新,还检测删除,新建操作(为了简化流程图,相应的代码没有展示在流程图中)。之后,我们将旧元素和当前元素,如果一些子元素被移除了,则我们需要卸载对应的组件并同时移除它。
接下去,在第二次迭代过程中,我们需要处理button,这个相对来说比较简单,因为button的子元素就是文本,内容就是‘set state button"。我们检测下之前的内容是否跟现在的保持一致,嗯,文本没有发生改变,所以我们不需要更新button。逻辑上来说这样很正确,其实这就是虚拟DOM的作用,现在虚拟DOM听起来就具体了些,是不是?React会维护内部DOM,同时只在需要时才去处理真正的DOM节点,通过这种方式,很自然的会提高性能。到这里,你应该已经能理解React的设计思想了,这之后,我们对ChildCmp进行更新,它的子元素会被遍历直到它的内容层级并进行更新。在我们的列子里,通过click和setState的调用,"click state message"会对this.props.message进行更新。
//... onClickHandler() { this.setState({ message: "click state message" }); } render() { return//... 现在我们要对元素内容进行更新,事实上,是替换它的内容。那么是如何进行更新的呢?一个类似拥有配置信息的配置对象会被解析,并且配置对象里的定义的动作会被执行。对应我们的例子,文本更新的配置会像如下:
{ afterNode: null, content: "click state message", fromIndex: null, fromNode: null, toIndex: null, type: "TEXT_CONTENT" }正如你所见,它几乎就是一个空对象,这个文本内容更新例子是相当直白的。配置对象里有很多字段,这是因为在对DOM节点进行移动时,配置对象会比文本更新的配置对象相对来说会更复杂些:
看下源码,这应该会让我们有个更清晰的认识:
//src enderersdomclientutilsDOMChildrenOperations.js#172 processUpdates: function(parentNode, updates) { for (var k = 0; k < updates.length; k++) { var update = updates[k]; switch (update.type) { case "INSERT_MARKUP": insertLazyTreeChildAt( parentNode, update.content, getNodeAfter(parentNode, update.afterNode) ); break; case "MOVE_EXISTING": moveChild( parentNode, update.fromNode, getNodeAfter(parentNode, update.afterNode) ); break; case "SET_MARKUP": setInnerHTML( parentNode, update.content ); break; case "TEXT_CONTENT": setTextContent( parentNode, update.content ); break; case "REMOVE_NODE": removeChild(parentNode, update.fromNode); break; } } }我们的实例会走到"TEXT_CONTENT"的分支里,然后这就是最后一步了,React调用setTextContent方法,此方法会对真正的DOM节点进行内容更改。
不错不错,最终内部被更新到了页面上,这就是一个重绘的过程了。还有什么东西没有讲到吗?嗯,不要着急,让我们先完成这个更新过程。所有的东西都已经准备完毕,所有我们组件的componentDidUpdate方法会被调用。那么,这种延迟调用是如何实现的呢?没错,就是使用事务包装器。就像之前提到的,‘脏’组件的更新是被ReactUpdateFlushtransaction给包装过的,其中一个包装器里就有调用this.callbackQueue.notifyAll的逻辑,也就是在这里,componentDidUpdate会被调用。完美!
现在,我们真的完成了整个过程。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/95957.html
摘要:技术上来说,当方法被调用后或者发生改变后,方法都会被调用。下一步,会设置为。之后,检测当前更新是否由更新引起的。这是因为,使用是导致组件持久化更新,而会被方法的返回值重新赋值。 接上文, React流程图:https://bogdan-lyashenko.gith... 更新组件 关于组件的更新,我们先看下代码里的注释: 对于已挂载组件的更新过程,React会首先调用component...
摘要:接上文,流程图我们已经知道挂载的工作流程,现在我们换个方向研究下方法,这个也是的重要组成部分。这个问题,我们会在下一篇文章中进行解答。。。 接上文, React流程图:https://bogdan-lyashenko.gith... this.setState 我们已经知道挂载的工作流程,现在我们换个方向研究下--setState方法,这个也是React的重要组成部分。 首先,为什么我...
摘要:源码里有个独立的模块管理组件的所有子元素。第一个,实例化子元素使用并挂载它们。至于具体挂载流程,基于子元素类型的不同而有不同的挂载过程。挂载的过程基本完成了。 接上文, React流程图:https://bogdan-lyashenko.gith... 创建初始子组件 在之前的步骤里,组件本身的构建已经完成,接下去,我们分析它们的子元素。总共分为两步:挂载子元素(this.mountC...
摘要:当鼠标事件发生时,组件的最外层会进行处理,然后通过几层包装器的处理后,会开始进行批量更新操作。在这之后,会将这些事件处理成常见到样子。 接上文, React流程图:https://bogdan-lyashenko.gith... 回到最初 在流程图中,也许你已经注意到,setState方法可以通过几种方式触发,更准确的说,可以分为是否由外部引起的(也就是是否由用户触发)。让我们看下如下...
摘要:接着,将返回的元素和之前的进行比较的,以验证是否真的需要更新。我们看下代码,代码比较简单好,对应于我们的这个列子,我们对于方法的更改并不会对方法造成影响。所以我们进入下一步,也就是对于节点的更新。 接上文, React流程图:https://bogdan-lyashenko.gith... 如果组件真的需要更新 在组件刚开始更新过程时,如果有定义componentWillUpdate方...
阅读 1924·2021-10-25 09:48
阅读 2703·2021-09-22 14:59
阅读 1668·2019-08-29 16:52
阅读 811·2019-08-29 16:07
阅读 2270·2019-08-29 12:38
阅读 1720·2019-08-26 13:23
阅读 840·2019-08-26 11:49
阅读 3168·2019-08-26 10:56