React diff 算法

  React是web前端UI庫,關注的是如何高效地根據數據渲染UI界面。virtual dom 與高效的diff算法的結合,使得當數據發生變動時,react 能經過簡潔高效的算法找出dom中真正變動,同時根據變動進行dom操做渲染UI界面。前端

  傳統的根據一個樹形結構到另一個樹形結構的裝換操做是一個複雜且耗時的過程,通常時間複雜度會達到O(n^3),加上每一個dom節點都是一個附帶大量信息的對象,通常的算法可能作到實時根據數據變動,更新UI視圖。react

  React根據dom樹的特定場景,制定了大量且高效的diff策略:web

  1. Web UI中dom節點的跨層次的移動操做不多,可忽略算法

  2. 擁有相同類型的組件有類似的樹形結構,不一樣類型的節點的樹形結構大機率不相同dom

  3. 對於同一層次的節點,能夠經過惟一的id進行區分性能

  根據上面的3點策略,兩顆dom數的比較,只會對同一層次的幾點進行比對。優化

  <1>當出現跨層次移動是,只有建立和刪除操做,是一種影響React 性能的操做,React 建議不要進行dom跨層次的操做,開發組件時,保持穩定的dom結構會有助於性能的提高,能夠經過CSS隱藏或顯示節點,而不是真的移除或添加節點。spa

  <2>若是是同一類型的組件,則按照繼續比較下一層的節點,若是不是同一類型的組件,則判斷爲dirty Component,從而根據新組件替換整個組件下的全部子組件,對於同一類型的組件,可能數據沒有發生變動或者UI視圖不須要根據,React 容許開發者經過shouldComponentUpdate(nextProps,nextState)來判斷該組件是否須要進行diffcode

  <3>對於同一層次下的子組件,react 建議添加key來惟一的區分,以提升diff的效率。首先會對的新的節點進行遍歷操做,經過惟一的key能夠找出須要新建、刪除、以及移位的節點。若是老集合中存在相同的節點則進行移位操做,避免的節點的新建刪除開銷(包括計算及dom操做)。移位操做算法以下:對象

  

let lastIndex = 0  // 記錄當前元素以前的元素在oldList中最靠後的位置 

  for(element in newList){     // element._mountIndex 是當前元素在老List的位置,newIndex 是當前元素在新 
         // LIst中的位置

       if(element._mountIndex < lastIndex)       move(element, newIndex)     lastIndex = Math.max(element._mountIndex, lastIndex)   }

     策略是若是當前元素在老List中的位置,小於在它以前元素在老List的中的位置,就說明當前元素須要向後移動才能變成新的List.

  總結:diff算法並非要構造一個新的樹,而比對找出變化的部分,來對老的dom樹進行最少的操做,從而優化UI更新的效率。

     

    參考:https://zhuanlan.zhihu.com/p/20346379

相關文章
相關標籤/搜索