iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >React中的Diff算法你了解吗
  • 646
分享到

React中的Diff算法你了解吗

2024-04-02 19:04:59 646人浏览 八月长安
摘要

目录一、Diff算法的作用二、React的Diff算法  1、什么是调和?2、什么是React diff算法?3、diff策略4、tree diff:5、comp

一、Diff算法的作用

渲染真实DOM的开销很大,有时候我们修改了某个数据,直接渲染到真实dom上会引起整个dom树的重绘和重排。我们希望只更新我们修改的那一小块dom,而不是整个dom,diff算法就帮我们实现了这点。

diff算法的本质就是:找出两个对象之间的差异,目的是尽可能做到节点复用。

注:此处说到的对象,指的其实就是Vue中的virtual dom(虚拟dom树),即使用js对象来表示页面中的dom结构。

二、React的Diff算法  

1、什么是调和

将Virtual DOM树转换成Actual DOM树的最少操作的过程称为调和。

2、什么是React diff算法?

diff算法是调和的具体实现。

3、diff策略

React用三大策略 将O(n3)复杂度 转化为O(n)复杂度

(1)策略一tree diffWEB UI中DOM节点跨层级的移动操作特别少,可以忽略不计。

(2)策略二component diff拥有相同类的两个组件 生成相似的树形结构,拥有不同类的两个组件 生成不同的树形结构。

(3)策略三element diff对于同一层级的一组子节点,通过唯一id区分。

4、tree diff:

(1)React通过updateDepthVirtual DOM树进行层级控制

(2)对树分层比较,两棵树只对同一层次节点进行比较。如果该节点不存在时,则该节点及其子节点会被完全删除,不会再进一步比较。

(3)只需遍历一次,就能完成整棵DOM树的比较。

如果DOM 节点出现了跨层级操作,Diff会怎么办?

答:Tree DIFF是对树的每一层进行遍历,如果某组件不存在了,则会直接销毁。如图所示,左边是旧属,右边是新属,第一层是R组件,一模一样,不会发生变化;第二层进入Component DIFF,同一类型组件继续比较下去,发现A组件没有,所以直接删掉A、B、C组件;继续第三层,重新创建A、B、C组件。

如上图所示,以A为根节点的整棵树会被重新创建,而不是移动,因此 官方建议不要进行DOM节点跨层级操作,可以通过CSS隐藏、显示节点,而不是真正地移除、添加DOM节点。

5、component diff :

React对不同的组件间的比较,有三种策略

(1)同一类型的两个组件,按原策略(层级比较)继续比较Virtual DOM树即可。

(2)同一类型的两个组件,组件A变化为组件B时,可能Virtual DOM没有任何变化,如果知道这点(变换的过程中,Virtual DOM没有改变),可节省大量计算时间,所以用户可以通过 shouldComponentUpdate() 来判断是否需要判断计算。

(3)不同类型的组件,将一个(将被改变的)组件判断为dirtycomponent(脏组件),从而替换整个组件的所有节点。

 注意:如上图所示,当组件D变为组件G时,即使这两个组件结构相似,一旦React判断D和G是不用类型的组件,就不会比较两者的结构,而是直接删除组件D,重新创建组件G及其子节点。虽然当两个组件是不同类型但结构相似时,进行diff算法分析会影响性能,但是毕竟不同类型的组件存在相似DOM树的情况在实际开发过程中很少出现,因此这种极端因素很难在实际开发过程中造成重大影响。

6、element diff 

当节点处于同一层级时,diff提供三种节点操作:删除、插入、移动

插入组件 C 不在集合(A,B)中,需要插入

删除:

(1)组件 D 在集合(A,B,D)中,但 D的节点已经更改,不能复用和更新,所以需要删除 旧的D ,再创建新的。

(2)组件D之前在集合(A,B,D)中,但集合变成新的集合(A,B)了,D 就需要被删除。

移动:组件D已经在集合(A,B,C,D)里了,且集合更新时,D没有发生更新,只是位置改变,如新集合(A,D,B,C),D在第二个,无须像传统diff,让旧集合的第二个B和新集合的第二个D 比较,并且删除第二个位置的B,再在第二个位置插入D,而是 (对同一层级的同组子节点) 添加唯一key进行区分,移动即可。

 移动情形一:新旧集合中存在相同节点但位置不同时,如何移动节点

(1)B不移动,不赘述,更新l astIndex=1

(2)新集合取得 E,发现旧不存在,故在lastIndex=1的位置 创建E,更新lastIndex=1

(3)新集合取得C,C不移动,更新lastIndex=2

(4)新集合取得A,A移动,同上,更新lastIndex=2

(5)新集合对比后,再对旧集合遍历。判断 新集合 没有,但 旧集合 有的元素(如D,新集合没有,旧集合有),发现 D,删除D,diff操作结束。

React中Diff算法实现的代码:

_updateChildren: function(nextNestedChildrenElements, transaction, context) {
    var prevChildren = this._renderedChildren;
    var removednodes = {};
    var mountImages = [];
    // 获取新的子元素数组
    var nextChildren = this._reconcilerUpdateChildren(
      prevChildren,
      nextNestedChildrenElements,
      mountImages,
      removedNodes,
      transaction,
      context
    );
    if (!nextChildren && !prevChildren) {
      return;
    }
    var updates = null;
    var name;
    var nextIndex = 0;
    var lastIndex = 0;
    var nextMountIndex = 0;
    var lastPlacedNode = null;
    for (name in nextChildren) {
      if (!nextChildren.hasOwnProperty(name)) {
        continue;
      }
      var prevChild = prevChildren && prevChildren[name];
      var nextChild = nextChildren[name];
      if (prevChild === nextChild) {
        // 同一个引用,说明是使用的同一个component,所以我们需要做移动的操作
        // 移动已有的子节点
        // NOTICE:这里根据nextIndex, lastIndex决定是否移动
        updates = enqueue(
          updates,
          this.moveChild(prevChild, lastPlacedNode, nextIndex, lastIndex)
        );
        // 更新lastIndex
        lastIndex = Math.max(prevChild._mountIndex, lastIndex);
        // 更新component的.mountIndex属性
        prevChild._mountIndex = nextIndex;
      } else {
        if (prevChild) {
          // 更新lastIndex
          lastIndex = Math.max(prevChild._mountIndex, lastIndex);
        }
        // 添加新的子节点在指定的位置上
        updates = enqueue(
          updates,
          this._mountChildAtIndex(
            nextChild,
            mountImages[nextMountIndex],
            lastPlacedNode,
            nextIndex,
            transaction,
            context
          )
        );
        nextMountIndex++;
      }
      // 更新nextIndex
      nextIndex++;
      lastPlacedNode = ReactReconciler.getHostNode(nextChild);
    }
    // 移除掉不存在的旧子节点,和旧子节点和新子节点不同的旧子节点
    for (name in removedNodes) {
      if (removedNodes.hasOwnProperty(name)) {
        updates = enqueue(
          updates,
          this._unmountChild(prevChildren[name], removedNodes[name])
        );
      }
    }
  }

三、基于Diff的开发建议

基于tree diff:

  • 开发组件时,注意保持DOM结构的稳定;即,尽可能少地动态操作DOM结构,尤其是移动操作。
  • 当节点数过大或者页面更新次数过多时,页面卡顿的现象会比较明显。
  • 这时可以通过 CSS 隐藏或显示节点,而不是真的移除或添加 DOM 节点。

基于component diff:

  • 注意使用 shouldComponentUpdate() 来减少组件不必要的更新。
  • 对于类似的结构应该尽量封装成组件,既减少代码量,又能减少component diff的性能消耗。

基于element diff:

  • 对于列表结构,尽量减少类似将最后一个节点移动到列表首部的操作,当节点数量过大或更新操作过于频繁时,在一定程度上会影响 React 的渲染性能。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容! 

--结束END--

本文标题: React中的Diff算法你了解吗

本文链接: https://www.lsjlt.com/news/142327.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • React中的Diff算法你了解吗
    目录一、Diff算法的作用二、React的Diff算法  1、什么是调和?2、什么是React diff算法?3、diff策略4、tree diff:5、comp...
    99+
    2022-11-13
  • Vue的diff算法原理你真的了解吗
    目录思维导图0. 从常见问题引入1. 生成虚拟dom1. h方法实现2. render方法实现3. 再次渲染2. diff算法1. 对常见的dom做优化情况1:末尾追加一个元素(头和...
    99+
    2022-11-13
  • Vue的虚拟DOM和diff算法你了解吗
    目录什么是虚拟DOM?为什么需要虚拟DOM?总结在vue 中 数据改变 -> 虚拟DOM(计算变更)-> 操作DOM -> 视图更新 虚拟DOM: js执行速度比较...
    99+
    2022-11-13
  • 详解react应用中的DOM DIFF算法
    目录前言 什么是Virtual DOM? 使用Virtual DOM的原因 DOM 渲染页面的操作流程 Virtual DOM的优势如何将DOM用virtual DOM 来表...
    99+
    2022-11-12
  • react中的虚拟dom和diff算法详解
    虚拟DOM的作用 首先我们要知道虚拟dom的出现是为了解决什么问题的,他解决我们平时频繁的直接操作DOM效率低下的问题。那么为什么我们直接操作DOM效率会低下呢? 比如我们创建一个d...
    99+
    2022-11-12
  • react中的axios模块你了解吗
    目录一、react中axios模块的使用1、基于Promise的HTTP库用在浏览器和node.js中2、创建XMLHttpRequest对象:3、在react中安装axios4、发...
    99+
    2022-11-13
  • 深入了解Vue2中的的双端diff算法
    目录简单diff算法更新文本节点key的作用如何移动呢双端diff算法比较方式非理想情况的处理方式今天又重读了vue2的核心源码,主要之前读vue2源码的时候纯属的硬记,或者说纯粹的...
    99+
    2023-02-08
    Vue双端diff算法 Vue diff算法
  • React中的Refs属性你来了解吗
    目录1 介绍2 使用方法2.1 createRef(版本>=React16.3)2.2 回调Refs2.3 String类型的Refs(已过时,不推荐使用)2.4 useRef...
    99+
    2022-11-13
  • React的事件处理你了解吗
    目录一、React的事件处理1、与DOM事件处理的不同之处(1)React事件的命名方式:小驼峰方式,DOM的命名方式是小写(2)事件处理函数是以对象的方式赋值,而不是以字符串的方式...
    99+
    2022-11-13
  • LeetCode 中的 Python 算法,你会了吗?
    LeetCode 是一个面向程序员的在线编程平台,它提供了大量的算法题目,让程序员在切磋中不断提升自己的编程技巧。Python 作为一门简洁、易学、高效的编程语言,自然也成为了 LeetCode 上的热门语言之一。本文将介绍一些常见的 Py...
    99+
    2023-09-07
    linux shell leetcode
  • react中的双向绑定你真的了解吗
    前言:因为项目原因需要学习另一个超级火的框架react, 因为之前一直使用vue进行开发,所以在学习react中会不自觉的代入一些vue中的概念来理解react中的实现,下面就通过对...
    99+
    2022-11-13
  • Laravel编程中的算法优化技巧你了解吗?
    Laravel是一个流行的PHP框架,它为开发人员提供了许多有用的工具和库,以便更轻松地开发Web应用程序。但是,在使用Laravel编写应用程序时,我们仍然需要考虑算法的效率。在本文中,我们将探讨一些Laravel编程中的算法优化技巧,...
    99+
    2023-09-25
    编程算法 django laravel
  • 你了解ASP编程算法中的Git重定向吗?
    ASP编程算法中的Git重定向是一个比较常见的技术,它可以帮助开发人员更好地管理项目代码。本文将介绍Git重定向的基本概念和使用方法,并提供一些演示代码,帮助读者更好地理解和应用这一技术。 一、什么是Git重定向 Git重定向是指将一个Gi...
    99+
    2023-08-05
    编程算法 git 重定向
  • Load算法在PHP编程中的应用,你了解吗?
    在PHP编程中,Load算法是一个非常重要的概念,它可以帮助我们优化程序的性能,提高程序的运行效率。Load算法是一种基于负载均衡的算法,它可以帮助我们将任务分配到多个处理器上,从而加快程序的运行速度。 Load算法在PHP编程中的应用非...
    99+
    2023-08-15
    面试 load 编程算法
  • React Diff算法不采用Vue的双端对比原因详解
    目录前言React 官方的解析Fiber 的结构Fiber 链表的生成React 的 Diff 算法第一轮,常见情况的比对第二轮,不常见的情况的比对重点如何协调更新位置信息小结图文解...
    99+
    2022-11-13
  • numy 算法在 ASP Windows 编程中的应用,你了解吗?
    ASP是一种非常受欢迎的Web应用程序开发语言,而在ASP Windows编程中,NumPy算法的应用也变得越来越普遍。NumPy是一个Python的数学库,可以帮助程序员更快速、更高效地处理数学计算。在本文中,我们将深入探讨NumPy算法...
    99+
    2023-09-04
    windows 编程算法 numy
  • 你了解 Python 和算法在编程中的重要性吗?
    Python 是一种高级编程语言,已经成为了数据科学、机器学习、人工智能等领域的事实标准。而在编程中,算法是必不可少的组成部分。本文将介绍 Python 和算法在编程中的重要性,并且还将演示一些代码。 Python 在编程中的重要性 Pyt...
    99+
    2023-07-19
    unix 编程算法 laravel
  • ASP技术在LeetCode算法题中的应用,你了解吗?
    随着计算机技术的不断发展,人工智能已经渗透到了各个领域中。其中,算法题也成为了人工智能领域的一个重要组成部分。而在LeetCode算法题中,ASP技术也被广泛应用。本文将为大家介绍ASP技术在LeetCode算法题中的应用。 一、什么是A...
    99+
    2023-11-15
    分布式 大数据 leetcode
  • 你真的了解 Java 分布式编程算法吗?
    Java分布式编程算法是一种处理分布式计算的技术,它可以通过不同的节点分布计算任务,将计算结果整合在一起。在本文中,我们将深入了解Java分布式编程算法,并提供一些示例代码来帮助您更好地理解。 Java分布式编程算法的基础概念 Java分布...
    99+
    2023-06-20
    教程 分布式 编程算法
  • 你了解 ASP 日志同步的编程算法吗?
    ASP 日志同步的编程算法是一种用于解决应用程序日志记录和监控的问题的技术。在本文中,我们将深入探讨 ASP 日志同步的编程算法,让您更深入地了解这项技术。 ASP 日志同步是一种将应用程序日志记录到中央日志存储库的技术。这种技术可以帮助开...
    99+
    2023-08-17
    日志 同步 编程算法
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作