简述
ReactDOMComponentTree主要是对DOM Node 和 ConponentInst做一些映射,不过这个映射不通过Map结构来处理,而是通过在它们自身上面挂载属性做缓存的方式来实现。
这样当给出一个DOM Node 或者 ConponentInst时候 就可以对应给出它们对应的DOM Node 或者 ConponentInst了。
API
方法名 | 作用 |
---|---|
getClosestInstanceFromNode | 根据传入的DOM Node返回临近的(实际上是往上找)ReactDOMComponent or ReactDOMTextComponent |
getInstanceFromNode | 根据传入的DOM Node返回对应的ReactDOMComponent or ReactDOMTextComponent实例 可能返回null |
getNodeFromInstance | 根据传入的组件实例获得对应的DOM Node |
precacheChildNodes | 为所有的子节点实例添加_hostNode属性进行缓存, 这个缓存操作是双向的 |
precacheNode | 使用给定的DOM node填充在给定的实例的_hostNode属性上 |
uncacheNode | 将给定实例的_hostNode设为null |
这之前,需要先弄清楚,DOM Node和Instance是什么。DOM Node这个不提默认大家知道,Instance这个,可以参见instantiateReactComponent返回的几种实例。
细节
getRenderedHostOrTextFromComponent
1 | function getRenderedHostOrTextFromComponent(component) { |
这个函数被导出多个方法调用到。它的作用是从给定的component(自定义组件或者空组件)一直向下钻,直到获取到一个component._renderedComponent === void 0
的组件并返回(如果一开始就满足这个条件就直接返回了传入的componet)。这个过程中如果component上已经有_renderedComponent
那么它会被赋值给component并再次重复这个步骤。
precacheNode
1 | function precacheNode(inst, node) { |
代码就三行,但是这里做了三件事:
- 获取hostInst 从inst上一直往下钻获取_renderedComponent 参见上面的分析
- 在实例上绑定_hostNode将其设为DOM Node
- 在DOM Node上将inst使用internalInstanceKey做key挂载好
所以这里的缓存是两步: 在DOM Node上缓存inst的同时也在实例上缓存了DOM Node
uncacheNode
1 | function uncacheNode(inst) { |
precacheNode的反向操作。双向解绑。
precacheChildNodes
1 | function precacheChildNodes(inst, node) { |
这个函数用处是遍历所有下级children并为其调用precacheNode进行缓存。
这个遍历是遍历当前实例下一级且只有这一级的children。缓存完毕之后更新_flags
,这里的运算是位或运算,只要inst._flags、Flags.hasCachedChildNodes
之一为1那么为1,否则同时为0就为0.
这个缓存过程是为了避免算法纬度达到n^2
。
这里注释里面提到这里代码存在的BUG: inst._renderedChildren
更新和这里的缓存会存在赛跑问题,所以更改它之前会调用prepareToManageChildren
来避免这种情况。不过就当前观察的版本15.6.2来说这个函数已经被移除了。后面会分析一下当前版本是怎样做的。
getClosestInstanceFromNode
这个函数逻辑有些小绕。它的逻辑是:
- 判断传入的DOM Node是否已经挂载internalInstanceKey属性,有则返回 否则下一步
- 一直往上找自己的父元素,直到找到一个已经被缓存internalInstanceKey属性的父元素
- 返回这个找到的元素,如果之前向上溯源超过两级就使用
precacheChildNodes(inst, node)
对这个元素的child进行缓存操作