目錄
二、React的Diff演算法  
2、什麼是React diff演算法? " >2、什麼是React diff演算法?
3、diff策略" >3、diff策略
三、基於Diff的開發建議
首頁 web前端 前端問答 react的diff方法是什麼

react的diff方法是什麼

Jan 03, 2023 pm 01:50 PM
react

react的diff方法可用於找出兩個物件之間的差異,目的是盡可能做到節點復用;diff演算法是調和的具體實現,而調和是指將Virtual DOM樹轉換成Actual DOM樹的最少操作的過程。

react的diff方法是什麼

本教學操作環境:Windows10系統、react18.0.0版、Dell G3電腦。

react的diff方法是什麼?

一、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 diff):Web UI中DOM節點跨層級的行動操作特別少,可以忽略不計。

#

    (2)策略二(component diff):有相同類別的兩個元件產生相似的樹狀結構,有兩個不同類別的元件產生不同的樹狀結構。

    #(3)策略三(

react的diff方法是什麼

##element diff):對於同一層級的一組子節點,透過唯一id區分。

4、tree diff:

(1)React透過updateDepth對Virtual DOM樹進行層級控制

react的diff方法是什麼

#。

(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(髒元件),從而取代整個元件的所有節點。

react的diff方法是什麼

 #注意:##如上圖所示,當元件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進行區分,移動即可。  

移動######################## 情形一:########################當新舊集合中存在相同節點但位置不同時,如何移動節點########## #####

react的diff方法是什麼

 

(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 的渲染效能。

推薦學習:《react影片教學

 

以上是react的diff方法是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

React前後端分離指南:如何實作前後端的解耦與獨立部署 React前後端分離指南:如何實作前後端的解耦與獨立部署 Sep 28, 2023 am 10:48 AM

React前後端分離指南:如何實現前後端的解耦和獨立部署,需要具體程式碼範例在當今的Web開發環境中,前後端分離已經成為一種趨勢。透過將前端和後端程式碼分開,可以讓開發工作更加靈活、高效,並且方便進行團隊協作。本文將介紹如何使用React實現前後端分離,從而實現解耦和獨立部署的目標。首先,我們要先理解什麼是前後端分離。傳統的Web開發模式中,前端和後端是耦合在

如何利用React和Flask建構簡單易用的網路應用 如何利用React和Flask建構簡單易用的網路應用 Sep 27, 2023 am 11:09 AM

如何利用React和Flask建構簡單易用的網路應用引言:隨著網路的發展,網路應用的需求也越來越多樣化和複雜化。為了滿足使用者對於易用性和效能的要求,使用現代化的技術堆疊來建立網路應用變得越來越重要。 React和Flask是兩個在前端和後端開發中非常受歡迎的框架,它們可以很好的結合在一起,用來建立簡單易用的網路應用。本文將詳細介紹如何利用React和Flask

如何利用React和RabbitMQ建立可靠的訊息應用 如何利用React和RabbitMQ建立可靠的訊息應用 Sep 28, 2023 pm 08:24 PM

如何利用React和RabbitMQ建立可靠的訊息傳遞應用程式引言:現代化的應用程式需要支援可靠的訊息傳遞,以實現即時更新和資料同步等功能。 React是一種流行的JavaScript庫,用於建立使用者介面,而RabbitMQ是一種可靠的訊息傳遞中間件。本文將介紹如何結合React和RabbitMQ建立可靠的訊息傳遞應用,並提供具體的程式碼範例。 RabbitMQ概述:

React Router使用指南:如何實現前端路由控制 React Router使用指南:如何實現前端路由控制 Sep 29, 2023 pm 05:45 PM

ReactRouter使用指南:如何實現前端路由控制隨著單頁應用的流行,前端路由成為了一個不可忽視的重要部分。 ReactRouter作為React生態系統中最受歡迎的路由庫,提供了豐富的功能和易用的API,使得前端路由的實作變得非常簡單和靈活。本文將介紹ReactRouter的使用方法,並提供一些具體的程式碼範例。安裝ReactRouter首先,我們需要

如何利用React與Apache Kafka建構即時資料處理應用 如何利用React與Apache Kafka建構即時資料處理應用 Sep 27, 2023 pm 02:25 PM

如何利用React和ApacheKafka來建立即時資料處理應用介紹:隨著大數據與即時資料處理的興起,建構即時資料處理應用成為了許多開發者的追求。 React作為一個流行的前端框架,與ApacheKafka作為一個高效能的分散式訊息系統的結合,可以幫助我們建立即時資料處理應用。本文將介紹如何利用React和ApacheKafka建構即時資料處理應用,並

PHP、Vue和React:如何選擇最適合的前端框架? PHP、Vue和React:如何選擇最適合的前端框架? Mar 15, 2024 pm 05:48 PM

PHP、Vue和React:如何選擇最適合的前端框架?隨著互聯網技術的不斷發展,前端框架在Web開發中起著至關重要的作用。 PHP、Vue和React作為三種代表性的前端框架,每一種都具有其獨特的特徵和優勢。在選擇使用哪種前端框架時,開發人員需要根據專案需求、團隊技能和個人偏好做出明智的決策。本文將透過比較PHP、Vue和React這三種前端框架的特徵和使

Java框架與前端React框架的整合 Java框架與前端React框架的整合 Jun 01, 2024 pm 03:16 PM

Java框架與React框架的整合:步驟:設定後端Java框架。建立專案結構。配置建置工具。建立React應用程式。編寫RESTAPI端點。配置通訊機制。實戰案例(SpringBoot+React):Java程式碼:定義RESTfulAPI控制器。 React程式碼:取得並顯示API回傳的資料。

如何利用React開發一個響應式的後台管理系統 如何利用React開發一個響應式的後台管理系統 Sep 28, 2023 pm 04:55 PM

如何利用React開發一個響應式的後台管理系統隨著互聯網的快速發展,越來越多的企業和組織需要一個高效、靈活、易於管理的後台管理系統來處理日常的操作事務。 React作為目前最受歡迎的JavaScript庫之一,提供了一種簡潔、高效和可維護的方式來建立使用者介面。本文將介紹如何利用React開發一個響應式的後台管理系統,並給出具體的程式碼範例。建立React專案首先

See all articles