Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

diff? #55

Open
bibi7 opened this issue Dec 15, 2019 · 0 comments
Open

diff? #55

bibi7 opened this issue Dec 15, 2019 · 0 comments

Comments

@bibi7
Copy link
Owner

bibi7 commented Dec 15, 2019

不拖了不拖了,总结下理解,源码阅读有空去隔壁的repo再写吧

先来看一版15的diff

React 源码剖析系列 - 不可思议的 react diff
React源码之Diff算法

react 15.x的diff策略只会进行横向的同级比较,基于这么几个diff策略原因:

  1. Web UI 中 DOM 节点跨层级的移动操作特别少,可以忽略不计。
  2. 拥有相同类的两个组件将会生成相似的树形结构,拥有不同类的两个组件将会生成不同的树形结构。
  3. 对于同一层级的一组子节点,它们可以通过唯一 id 进行区分。

所以整个一套的diff可以这么从上往下来划分:

  1. tree diff

  2. component diff

  3. element diff

细心点可以发现这个细粒度是层次往下递进的

对于tree diff而言

react的同层级比较通过updateDepth来控制。只有同层级才会进行比较,即同一个父节点下的所有子节点。对于不同层级的节点,只有增删两个操作。

对于component diff而言

如果是同一种类型的组件,那么dom层次都是一样的,可以继续比较dom的差异。
如果是不同的组件,默认为dirty component,直接替换组件下面的全部子节点。这是因为不同的component很少会存在类似的dom结构

对于element diff而言

当节点处于同一层级时,React diff 提供了三种节点操作,分别为:INSERT_MARKUP(插入),**MOVE_EXISTING(移动)**和 REMOVE_NODE(删除)

具体统计的diff思路为:
遍历新老集合(这里有key的话会对性能有更大的帮助)

  1. 一开始会创建一个变量lastIndex,且默认为0
  2. 从新集合开始遍历,判断是否在老集合中也存在
    2.1 未存在则直接插入,并且更新lastIndex
    2.2 存在则取到老集合的节点index坐标,和lastIndex比对if (child._mountIndex < lastIndex),小于则进行节点操作。同时更新lastIndex
  3. 依次遍历到最后,最后还要遍历依次老集合,查看是否有元素不在新集合中的,则删除

lastIndex的更新思路为取最大值: lastIndex = Math.max(prevChild._mountIndex, lastIndex)

16版的diff

React Diff 源码分析
Deep In React
yck 组件更新流程

在调度之后进行调和,也就是diff
根据我们render出来的东西,一样也会存在着新老dom之分。

  1. returnFiber:父组件。
  2. currentFirstChild:父组件的第一个 child。如果你还记得 fiber 的数据结构的话,应该知道每个 fiber 都有一个 sibling 属性指向它的兄弟节点。因此知道第一个子节点就能知道所有的同级节点。
  3. newChild:render出来的即将更新的节点。

根据newChild的类型不同,会有不同的处理方法,可能是 TextNode、可能是 ReactElement,可能是数组。重点放在可迭代类型上。
React16的diff算法采用从链表头部开始比较的算法,是层次遍历,算法是建立在一个节点的插入、删除、移动等操作都是在节点树的同一层级中进行的,核心就是如何diff两个子节点数组。
核心函数
想了想这一部分还是要看一下源码理解才能更深。下面的部分专门放源码解读的repo了。具体见隔壁repo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant