然后给每个节点生成一个唯一的标志: 图片 在遍历的过程中,每遍历到一个节点,就将新旧两棵树作比较,并且只对同一级别的元素进行比较: 图片 也就是只比较图中用虚线连接起来的部分,把前后差异记录下来。...react diff算法通过新旧节点比较后,如果发现了key值相同的新旧节点,就会执行移动操作(然后依然按原策略深入节点内部的差异对比更新),而不会执行原策略的删除旧节点,创建新节点的操作。...比如当前遍历的所有节点类型都相同,其内部文本不同,在用index作key的情况下,当我们对原始的数据list进行了某些元素的顺序改变操作,导致了新旧集合中在进行diff比较时,相同index所对应的新旧的节点其文本不一致了...如果存在新旧集合中,相同的key值所对应的节点类型不同(比如从span变成div),这相当于完全替换了旧节点,删除了旧节点,创建了新节点。 如果新集合中,出现了旧集合没有存在过的key值。...例如某个节点的key之前为1,现在为100,但旧集合中其他节点也没有使用100这个key值。说明没发生过移动操作,此时diff算法会对对应的节点进行销毁并重新创建。
然后给每个节点生成一个唯一的标志:图片 在遍历的过程中,每遍历到一个节点,就将新旧两棵树作比较,并且只对同一级别的元素进行比较:图片 也就是只比较图中用虚线连接起来的部分,把前后差异记录下来。...react diff算法通过新旧节点比较后,如果发现了key值相同的新旧节点,就会执行移动操作(然后依然按原策略深入节点内部的差异对比更新),而不会执行原策略的删除旧节点,创建新节点的操作。...React官方建议不要用遍历的index作为这种场景下的节点的key属性值。...如果存在新旧集合中,相同的key值所对应的节点类型不同(比如从span变成div),这相当于完全替换了旧节点,删除了旧节点,创建了新节点。如果新集合中,出现了旧集合没有存在过的key值。...例如某个节点的key之前为1,现在为100,但旧集合中其他节点也没有使用100这个key值。说明没发生过移动操作,此时diff算法会对对应的节点进行销毁并重新创建。
react diff算法通过新旧节点比较后,如果发现了key值相同的新旧节点,就会执行移动操作(然后依然按原策略深入节点内部的差异对比更新),而不会执行原策略的删除旧节点,创建新节点的操作。...React官方建议不要用遍历的index作为这种场景下的节点的key属性值。...比如当前遍历的所有节点类型都相同,其内部文本不同,在用index作key的情况下,当我们对原始的数据list进行了某些元素的顺序改变操作,导致了新旧集合中在进行diff比较时,相同index所对应的新旧的节点其文本不一致了...如果存在新旧集合中,相同的key值所对应的节点类型不同(比如从span变成div),这相当于完全替换了旧节点,删除了旧节点,创建了新节点。 如果新集合中,出现了旧集合没有存在过的key值。...例如某个节点的key之前为1,现在为100,但旧集合中其他节点也没有使用100这个key值。说明没发生过移动操作,此时diff算法会对对应的节点进行销毁并重新创建。
,会尽量减少数组遍历的次数 //跳出循环的条件是,在遍历新老数组的过程中,找到第一个不能复用的节点 for (; oldFiber !...,那么就执行deleteRemainingChildren(),删除旧节点 (3) 如果旧节点都已经被复用完了,但是仍有部分新节点需要被创建的话,则循环剩余数组的长度,并依次创建新节点(部分代码与上面重复...没有值的话,说明不是由旧节点更新来的,而是新插入的节点,返回lastPlacedIndex 四、mapRemainingChildren 作用: 将旧节点用 Map 结构集合起来,方便 newFiber...key的话,则说明是文本节点,则以index-value的形式存储,最终返回这个 Map 对象 五、updateFromMap 作用: 在 Map 对象中查找有没有 key/index 相同的 fiber...//如果是文本节点的话,会从 Map 对象中寻找是否有相同的 index(为什么不是key?
上一章中 react 的 render 阶段,其中 begin 时会调用 reconcileChildren 函数, reconcileChildren 中做的事情就是 react 知名的 diff 过程...、newChild、lanes 四个参数,其中,根据 newChid 的类型,我们主要关注几个比较常见的类型的 diff,单 React 元素的 diff、纯文本类型的 diff 和 数组类型的 diff...diff 比较简单,只需要判断当前父 fiber 的第一个旧子 fiber 类型: 当前 fiber 也为文本类型的节点时,deleteRemainingChildren 对第一个旧子 fiber 的所有兄弟...指向父 fiber 所以对文本类型 diff 的流程如下: 图片 新内容为数组类型 上面所说的两种情况,都是一个或多个子 fiebr 变成单个 fiber。...return resultingFirstChild; } 从上述代码我们可以得知,对于新增内容为数组时,react 会对旧 fiber 和 newChildren 进行遍历。
上一章中 react 的 render 阶段,其中 begin 时会调用 reconcileChildren 函数, reconcileChildren 中做的事情就是 react 知名的 diff 过程...、newChild、lanes 四个参数,其中,根据 newChid 的类型,我们主要关注几个比较常见的类型的 diff,单 React 元素的 diff、纯文本类型的 diff 和 数组类型的 diff...diff 比较简单,只需要判断当前父 fiber 的第一个旧子 fiber 类型:当前 fiber 也为文本类型的节点时,deleteRemainingChildren 对第一个旧子 fiber 的所有兄弟...指向父 fiber所以对文本类型 diff 的流程如下: 图片新内容为数组类型上面所说的两种情况,都是一个或多个子 fiebr 变成单个 fiber。...return resultingFirstChild;}从上述代码我们可以得知,对于新增内容为数组时,react 会对旧 fiber 和 newChildren 进行遍历。
当修改的内容为可迭代类型,调用reconcileChildrenIterator函数参考React实战视频讲解:进入学习reconcileSingleElementreconcileSingleElement...如果不为文本类型,那么给旧的节点添加Deletion标记,通过createFiberFromText创建新的文本类型节点,并指向父级fiber。...return updateSlot(returnFiber, oldFiber, init(payload), lanes); } } } // 如果是数组或者可迭代的...react中的diff策略,则表现为tree diff、component diff、element diff。...图片总结这一章讲述了,react的diff过程,也学习了react的diff策略,经过上述的处理之后就会走到completeUnitWork,在这个过程中我们会根据新生成的fiber树去创建dom元素,
当修改的内容为REACT_LAZY_TYPE类型,递归调用reconcileChildFibers函数。当修改的内容问纯文本类型,调用reconcileSingleTextNode函数。...当修改的内容为数组类型,调用reconcileChildrenArray函数。...当修改的内容为可迭代类型,调用reconcileChildrenIterator函数reconcileSingleElementreconcileSingleElement的源码如下: function...fiber与新生成的ReactElement的key和type进行比较:如果旧的fiber子节点与新的子节点的key和type不一致,给当前的旧的fiber子节点添加上Deletion标记,继续遍历其兄弟节点...如果旧的fiber子节点与新的子节点的类型匹配不上,则会直接给旧的fiber子节点打上Deletion标记,移除子节点以及后面的所有兄弟节点。
在react中采用的是diff算法来对比新旧虚拟节点,从而更新节点。...在交叉对比中,当新节点跟旧节点头尾交叉对比没有结果时,会根据新节点的key去对比旧节点数组中的key,从而找到相应旧节点(这里对应的是一个key => index 的map映射)。...其实如果说只是文本内容改变了,不写key反而性能和效率更高,主要是因为不写key是将所有的文本内容替换一下,节点不会发生变化,而写key则涉及到了节点的增和删,发现旧key不存在了,则将其删除,新key...所以说key是给每一个vnode的唯一id,可以依靠key,更准确, 更快的拿到oldVnode中对应的vnode节点,高效和准确的更新节点 误区 很多人在写key是通常是将循环的index值写入,这样又写了...因为在react中如果你没有指定任何 key,react 会发出警告,并且会把数组的索引当作默认的 key。但是如果想要对列表进行重新排序、新增、删除操作时,把数组索引作为 key 是有问题的。
Iterator迭代器 Iterator(迭代器)是一种接口,也可以说是一种规范。为各种不同的数据结构提供统一的访问机制。...let arr = [{num:1},2,3] let it = arr[Symbol.iterator]() // 获取数组中的迭代器 console.log(it.next()) // { value...图片 这就意味着,如果 dom 节点发生了跨层级移动,react 会删除旧的节点,生成新的节点,而不会复用。...,两者区别如下: forEach()方法会针对每一个元素执行提供的函数,对数据的操作会改变原数组,该方法没有返回值; map()方法不会改变原数组的值,返回一个新数组,新数组中的值为原数组调用函数处理之后的值...明文传输: 协议中的报文使用的是文本形式,这就直接暴露给外界,不安全。
当React渲染组件时,会创建一个虚拟DOM树,并与之前的虚拟DOM树进行比较,找出差异,并将差异应用到真实的DOM上。...在这个比较过程中,React需要对每个元素进行唯一性判断,以确定是否需要更新该元素。而这个唯一性判断就依赖于key属性。React使用key属性的值来判断元素是否相同。...使用了一个简单的数组作为组件的state,每个数组元素包含一个id和text属性。...在渲染列表项时,我们使用了每个元素的id作为key属性。 当用户点击“Update”按钮时,我们改变了数组中第二个元素的文本内容,并重新设置state。...由于该元素的id没有改变,React会认为它是同一个元素,并且只会更新它的文本内容,而不是重新渲染整个列表。这样就可以大大提高渲染性能,避免不必要的重绘操作。
从 h 函数说起 观察主流的虚拟 DOM 库(snabbdom、virtual-dom),通常都有一个 h 函数,也就是 React 中的 React.createElement,以及 Vue 中的 render...,且新旧节点 tag 相同 对比新旧节点的属性 对比新旧节点的子节点差异,通过 key 值进行重排序,key 值相同节点继续向下遍历 新旧节点如果都是 VText,判断两者文本是否发生变化 其他情况直接用新节点替代旧节点...找到数组中首部和尾部公共的节点,并在两端移动 该方法通过比对两端的 key 值,找到旧节点(A) 和新节点(B)中索引相同的节点。...稍后,我们将把旧子节点中的节点位置分配给这个数组。.... == -1 然后,我们构建一个对象 I,它的键表示新子节点的 key 值,值为子节点在剩余节点数组中的位置。
它是一个替代indexOf,开发人员用来检查数组中是否存在值,indexOf是一种尴尬的使用,因为它返回一个元素在数组中的位置或者-1当这样的元素不能被找到的情况下。...在ES6,要检查是否存在值,你需要做一些判断,因为他们没有匹配到值,Array.prototype.indexOf返回-1变成了true(转换成true),但是当匹配的元素为0位置时候,该数组包含元素,...Object.values/Object.entries 在ES8 /ES2017之前,Javascript开发者需要迭代一个对象的自身属性时候不得不用Object.keys,通过迭代且使用obj[key...]获取value值返回一个数组。...共享内存与原子操作 当内存被共享时,多个线程可以并发读、写内存中相同的数据。原子操作可以确保那些被读、写的值都是可预期的,即新的事务是在旧的事务结束之后启动的,旧的事务在结束之前并不会被中断。
领取专属 10元无门槛券
手把手带您无忧上云