react的diff算法基于两个假设:

1.不同类型的元素会产生不同的树

2.通过设置key,开发者能够提示那些子组件是稳定的

diff算法

当比较两个树时,react首先会比较两个根节点,接下来具体的行为取决于根节点的类型。

1.不同类型的元素

如果树的根元素是不同的类型,那么React会拆掉整个旧的书并且用新的树替换。当树被拆掉,DOM节点会被销毁,组件实例会调用componentWillUnmount钩子函数。
当创建出一个新的树,新的DOM节点会被插入到DOM中。组件实例调用componentWillMount钩子和componentDidMount钩子

如从<a>到<img>,从<div>到<from>,<Article>到<Commit>都会导致重新创建。并且state会被销毁

2.相同类型的DOM元素

当比较两个相同类型的React DOM元素,React会查看它们两个的属性,React仅仅更新被改变的属性,并不会更新底层的DOM节点。当处理完根DOM节点之后,
React又会递归的比较它们的子元素

3.相同类型的组件元素

当组件被更新,组件的实例会保持不变,组件的state还是存在。React更新下面组件实例的props,下面的组件实例调用componentWillReceiveProps钩子和componentWillUpdate钩子。接下来调用render方法并且diff算法在之前的结果和新的结果上递归

在子元素上递归

qq默认情况,当在DOM节点的子元素上递归,React会同时遍历两个列表上的子元素,并且当发现它们不同就会生成一个变化,如下的例子:


<ul>
<li>first</li>
<li>second</li>
</ul>
变为
<ul>
<li>first</li>
<li>second</li>
<li>third</li>
</ul>

React会捕获到两个<li>first</li>,两个<li>second</li>,然后将<li>third</li>插入。如果在列表中最开始插入了一个元素,那么性能就会很不好,如下:


<ul>
<li>Duke</li>
<li>Villanova</li>
</ul>
变为
<ul>
<li>Connecticut</li>
<li>Duke</li>
<li>Villanova</li>
</ul>

这种情况React会改变每一个子元素。可以通过给元素设置key来解决这个问题。

如果给上面列表中的li设置key


<ul>
<li key='1'>Duke</li>
<li key='2'>Villanova</li>
</ul>
变为
<ul>
<li key='3'>Connecticut</li>
<li key='1'>Duke</li>
<li key='2'>Villanova</li>
</ul>

React能够知道<li key='3'>Connecticut</li>是新插入的,并且元素 <li key='1'>Duke</li>和<li key='2'>Villanova</li>仅仅被移动
兄弟元素之间的key需要是唯一的,但是不需要全局唯一。

注:
1.diff算法不会匹配两个不同组件类型的子树,如果你发现你在两个具有非常相似输出的不同组件之间进行交互,你可以把它们写成一个组件
2.key应该是稳定的,可预测的,唯一的。不稳定的key(如:通过Math.random()产生的key)可能会导致组件实例和DOM节点做一些不必要的重建
3.当组件的state或者props改变,React通过把新返回的组件和之前渲染的组件进行比较来确定是否需要更新DOM,如果不相等,就更新DOM
4.在一些情况下,通过重写组件的shouldComponentUpdate钩子函数,可以提高性能。这个钩子函数在重新渲染组件之前被调用,这个钩子的默认行为时返回true,
如果你确定在一些情况下,你的组件不需要更新,那么你可以让shouldComponentUpdate钩子返回false。在组件的shouldComponentUpdate钩子返回false
这样会跳过整个渲染过程,组件不会调用render方法,也不会通过diff算法比较新返回的组件是否也之前的组件相同

React——diff算法的更多相关文章

  1. React Diff 算法

    React介绍 React是Facebook开发的一款JS库,用于构建用户界面的类库. 它采用声明式范例,可以传递声明代码,最大限度地减少与DOM的交互. 特点: 声明式设计:React采用声明范式, ...

  2. react diff算法浅析

    diff算法作为Virtual DOM的加速器,其算法的改进优化是React整个界面渲染的基础和性能的保障,同时也是React源码中最神秘的,最不可思议的部分 1.传统diff算法计算一棵树形结构转换 ...

  3. React Diff算法

    Web界面由DOM树来构成,当其中某一部分发生变化时,其实就是对应的某个DOM节点发生了变化.在React中,构建UI界面的思路是由当前状态决定界面.前后两个状态就对应两套界面,然后由React来比较 ...

  4. React Diff算法一览

    前言 diff算法一直是React系统最核心的部分,并且由于演化自传统diff,使得比较方式从O(n^3)降级到O(n),然后又改成了链表方式,可谓是变化万千. 传统Diff算法 传统diff算法需要 ...

  5. React基础(Diff算法,属性和状态)

    1.React的背景原理 (1)React Diff算法流程 (2)React虚拟DOM机制 React引入了虚拟DOM(Virtual DOM)的机制:在浏览器端用Javascript实现了一套DO ...

  6. ReactiveNative学习之Diff算法

    React 源码剖析系列 - 不可思议的 react diff深入浅出React(四):虚拟DOM Diff算法解析React diff 算法总结链接引用的文章React出于性能的考虑,为了避免频繁操 ...

  7. React 源码剖析系列 - 不可思议的 react diff

      简单点的重复利用已有的dom和其他REACT性能快的原理. key的作用和虚拟节点 目前,前端领域中 React 势头正盛,使用者众多却少有能够深入剖析内部实现机制和原理. 本系列文章希望通过剖析 ...

  8. 直接操作DOM一定比虚拟DOM操作耗时,diff算法,key值,虚拟 DOM的定义

    直接操作DOM一定比虚拟DOM操作耗时吗? 或者一次直接DOM操作一定比一次虚拟DOM操作耗时吗? 1)虚拟DOM的本质就是一个JS对象,虚拟DOM减少了真实DOM的操作,当修改数据的时候,就是修改虚 ...

  9. diff算法深入一下?

    文章转自豆皮范儿-diff算法深入一下 一.前言 有同学问:能否详细说一下 diff 算法. 简单说:diff 算法是一种优化手段,将前后两个模块进行差异化比较,修补(更新)差异的过程叫做 patch ...

随机推荐

  1. 反射应用--IOC和AOP

    反射最大的价值就是用来写框架,下面贴出自己的3篇代码,模拟实现SPING框架的bean工厂,IOC,AOP.当然这里重点是在利用反射实现功能,为了图方便,我用的是Properties文件,关于XML后 ...

  2. centos yum方式安装net-snmp v3

    SNMPv3的安全报头采用用户安全模式(USM),其提供具有机密性和完整性的网络管理通信.机密性通过采用数据加密标准(DES)来提供.尽管 这一算法以脆弱性著称(由于它采用的是40位的密钥),但与明文 ...

  3. 吴恩达深度学习笔记(deeplearning.ai)之卷积神经网络(一)

    Padding 在卷积操作中,过滤器(又称核)的大小通常为奇数,如3x3,5x5.这样的好处有两点: 在特征图(二维卷积)中就会存在一个中心像素点.有一个中心像素点会十分方便,便于指出过滤器的位置. ...

  4. Swing小技巧总结

    1. 使JDialog位于屏幕的中央 public void setToScreenCenter(JDialog jd) {           Dimension screenSize = Tool ...

  5. HDU3488 Tour [有向环覆盖 费用流]

    Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submis ...

  6. R语言-选择样本数量

    功效分析:可以帮助在给定置信度的情况下,判断检测到给定效应值时所需的样本量,也可以在给定置信水平的情况下,计算某样本量内可以检测到的给定效应值的概率 1.t检验 案例:使用手机和司机反应时间的实验 l ...

  7. 学习docker on windows (1): 为什么要使用docker

    为什么要用Docker? 如果我们想使用某种pc软件, 那么在互联网上查找并安装软件的流程大致如下图: 那么这就有几个问题要弄清楚: 从哪里获得软件 App Store Linux的包管理 从某些网站 ...

  8. 分布式服务dubbo使用

    SOA 服务框架dubbo 节点角色说明: Provider: 暴露服务的服务提供方. Consumer: 调用远程服务的服务消费方. Registry: 服务注册与发现的注册中心. Monitor: ...

  9. Base64算法原理

    3个Byte (3 X 8 = 24 bits) 以3个字节为单位,依次取6位数据,并在前面补上2个0.这样就增加了一个字节的数据.

  10. 集合的综合练习:Poker牌

    /* 刘意教程示例:*/ package cn.onecool.cot; import java.util.ArrayList; import java.util.Collections; impor ...