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. redis五大类型用法

    Redis五大类型:字符串(String).哈希/散列/字典(Hash).列表(List).集合(Set).有序集合(sorted set)五种Controller:@Resource RedisTe ...

  2. Windows脚本修改主机名-不重启

    windows通过脚本方式修改主机名的方法有很多种,下面介绍修改注册表方式的脚本. 使用方法: 1 打开cmd,假如脚本名为ModifyHostname.bat 2 执行脚本,并加入脚本参数,其中第一 ...

  3. hadoop - spark on yarn 集群搭建

    一.环境准备 1. 机器: 3 台虚拟机 机器 角色  l-qta3.sp.beta.cn0 NameNode,ResourceManager,spark的master l-querydiff1.sp ...

  4. 《struts2》:指定多个配置文件和默认Action

    转载:http://m.blog.csdn.net/article/details?id=51212968

  5. Struts2 (一)

    1 三层架构 2 MVC框架的原理 3 什么是Struts2 Struts2是一个非常优秀的MVC框架,基于Model2设计模式. 是由传统的Struts1和WebWork两个经典的框架发展而来的. ...

  6. redis数据类型-列表类型

    列表类型 列表类型(list)可以存储一个有序的字符串列表,常用的操作是向列表两端添加元素,或者获得列表的某一个片段. 列表类型内部是使用双向链表(double linked list)实现的,所以向 ...

  7. 动态库Link error 一种可能

    一般出现link error都是链接时找不到对应函数. 前些天出现这种错误,我反复地检查,都发现动态库里明确的是有对应函数的. 代码里有这样一句#pragma comment(lib,"li ...

  8. spark头脑镜像

    思考是一件有意思的事情.遇到问题,思考出结论,那么脑子里面的过程是什么呢,或者脑子里面是什么呢.我一直认为,这团团的里面是一个模糊的n维空间.理解一个复杂的系统.公式.算法,都要在这个n维空间里具象化 ...

  9. crontab 定时任务守护程序,停止服务器时出现 job for * canceled

    (1)首先要在程序启动的时候加入定时任务到crontab #! /bin/shmkdir -p /home/apps/components/ams/ 2>/dev/nullcp ./amswat ...

  10. 一个 div 手写红绿灯- 分别用css3 和 js 实现

    [要求] 一个div,配合 css3 或者 js 实现红绿灯切换的效果. [思路] 使用 css3,要实现红绿灯颜色的变换必然要用到 animation 动画,通过 keyframes 控制颜色的渐变 ...