中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

react的diff方法怎么使用

發布時間:2023-01-03 14:06:21 來源:億速云 閱讀:124 作者:iii 欄目:web開發

今天小編給大家分享一下react的diff方法怎么使用的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

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

一、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)策略三(element diff):對于同一層級的一組子節點,通過唯一id區分。

react的diff方法怎么使用

4、tree diff:

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

(2)對樹分層比較,兩棵樹只對同一層次節點進行比較。如果該節點不存在時,則該節點及其子節點會被完全刪除,不會再進一步比較。

(3)只需遍歷一次,就能完成整棵DOM樹的比較。

如果DOM 節點出現了跨層級操作,Diff會怎么辦?

答:Tree DIFF是對樹的每一層進行遍歷,如果某組件不存在了,則會直接銷毀。如圖所示,左邊是舊屬,右邊是新屬,第一層是R組件,一模一樣,不會發生變化;第二層進入Component DIFF,同一類型組件繼續比較下去,發現A組件沒有,所以直接刪掉A、B、C組件;繼續第三層,重新創建A、B、C組件。

react的diff方法怎么使用

如上圖所示,以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的diff方法怎么使用”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

连城县| 壤塘县| 武山县| 鹤峰县| 丰顺县| 东阿县| 丰宁| 泽普县| 城口县| 宁阳县| 旬阳县| 远安县| 永宁县| 海林市| 吉安县| 桂平市| 沙田区| 辽宁省| 嘉祥县| 鹤山市| 惠来县| 洪湖市| 舒城县| 长岛县| 巢湖市| 江源县| 寻甸| 武清区| 和政县| 曲靖市| 宣恩县| 舟山市| 北川| 百色市| 专栏| 凯里市| 奉贤区| 顺平县| 蒙阴县| 临泽县| 海宁市|