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. 【转】Robust regression(稳健回归)

    Robust regression(稳健回归) 语法 b=robustfit(X,y) b=robustfit(X,y,wfun,tune) b=robustfit(X,y,wfun,tune,con ...

  2. LINUX获取文件信息

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  3. 2018Pycharm激活方法

    1.将"0.0.0.0 account.jetbrains.com"添加到hosts文件中 2.打开http://idea.lanyus.com/ 3.获取激活码,粘贴到第二个选项 ...

  4. javase学习小结三

    格式标识符: System.out.printf("%d,%f,%5d,%-9.4f,%%,%13e",67,78.9,89,78.9,567.345); 输出结果为:67,78. ...

  5. Install MongoDB on Linux Systems 速记

    下载mongodb最新版本: 下载链接:http://pan.baidu.com/s/1kTDnkyz curl -O http://downloads.mongodb.org/linux/mongo ...

  6. ABP官方文档翻译 2.6 定时

    定时 介绍 时钟 客户端 时区 客户端 Binders和Converters 介绍 一些应用只针对一个时区,而其他的一些已用则有许多不同的时区.为了满足这样的需求和集中的时间操作,Abp提供了时间操作 ...

  7. BZOJ 1492: [NOI2007]货币兑换Cash [CDQ分治 斜率优化DP]

    传送门 题意:不想写... 扔链接就跑 好吧我回来了 首先发现每次兑换一定是全部兑换,因为你兑换说明有利可图,是为了后面的某一天两种卷的汇率差别明显而兑换 那么一定拿全利啊,一定比多天的组合好 $f[ ...

  8. oracle 字符串截取substr和instr

    SUBSTR(string,start_position,[length])    求子字符串,返回字符串解释:string 元字符串       start_position   开始位置(从0开始 ...

  9. 【linux之用户,密码,组管理】

    一.用户及密码 用户账户 超级用户:UID=0 root 普通用户:UID!=0 系统用户: 0<UID<500 为了维持系统的某些功能或者实现某些服务 不能完成登录时候的身份验证 普通用 ...

  10. linux下qt的安装

    2.1环境的搭建 linux-> 2.1.1 ./qt-opensource-linux-x86-5.5.0.run 2.1.2 vim /etc/profile (.bashrc) expor ...