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

溫馨提示×

溫馨提示×

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

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

React中調和算法Diffing算法策略的示例分析

發布時間:2021-12-29 12:43:51 來源:億速云 閱讀:202 作者:小新 欄目:開發技術

這篇文章主要為大家展示了“React中調和算法Diffing算法策略的示例分析”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“React中調和算法Diffing算法策略的示例分析”這篇文章吧。

算法策略

React的調和算法,主要發生在render階段,調和算法并不是一個特定的算法函數,而是指在調和過程中,為提高構建workInProcess樹的性能,以及Dom樹更新的性能,而采用的一種策略,又稱diffing算法。 在React 的官網上描述“Diffing” 算法時,提到了“diffing two trees”,但是在源碼實現時,并不是創建好兩棵樹后,再從上往下的diffing這兩棵樹。這個diffing發生在搭建子節點時, 實際是新生成的ReactElement 與 current樹上fibe節點的diffing。 為了將diffing算法的時間復雜度控制在O(n)(樹diff的時間復雜度涉及到樹的編輯距離,可以看這里), 采用了如下策略:

只比較同層級的節點,(貌似這一點沒有在官網中提到)

對于單節點比較,如果當前節點type 和 key 不相同,不再比較其下子節點,直接刪掉該節點及其下整棵子樹,根據ReactElement重新生成節點樹。因為React認為不同類型的組件生成的樹形結構不一樣,不必復用。

如果子節點是數組,可根據唯一的key值定位節點進行比較,這樣即使子節點順序發生變化,也可以根據key值進行復用。

值得注意的是,所有節點的diffing都會比較key,key 默認值為null。若是沒有設置,則null是恒等于null的,認為key是相同的。

單節點diffing

單個節點進行diffing時,會diffing兩組屬性:fibe.elementType vs ReactElement.type , fibe.key vs ReactElement.key, 如果這兩組屬性都相等,數據結構的物理空間會有如下復用邏輯(詳見源碼reconcileSingleElement函數):

  1. 如果current fibe 存在 alternate 節點,(這意味著這個fibe節點之前參與過調和),則復用該alternate節點的物理空間;否則需要clone current fibe節點,占用新的物理空間

  2. 對應的instance 或者 Dom 會被復用

  3. current fibe 下的child樹也會被直接掛載過來(下一步遞歸子節點時,會被使用)

如果兩組屬性有一個不相等:

  • fibe 根據ReactElement重新創建

  • 對應的instance和Dom 也會重建

  • child 樹全部刪除。

如果生成的ReactElement 是單節點,但是對應的current樹上是多節點時,會從逐一查找有沒有匹配的,找到匹配的,其他的都刪除;找不到,全部刪除。例如Couter組件有如下邏輯:當點擊次數大于10時,隱藏點擊按鈕。當到達第10次時,span節點會被復用。

class Counter extends React.Component{
    state={
        count:0
    }
    addCount = ()=>{
        const count = this.state.count+1;
        this.setState({count})
    }
    componentDidUpdate(){
        console.log("updated")
    }
    render(){
        return this.state.count < 10 ? [
            <button onClick={this.addCount}>點擊</button>
            <span>點擊次數:{this.state.count}</span>
        ]:<span>點擊次數:{this.state.count}</span>;
    }
}

數組節點diffing

數組節點進行diffing時,流程比較復雜:(源碼見reconcileChildrenArray函數)

React中調和算法Diffing算法策略的示例分析

中間有兩次重要的遍歷,第一次按index遍歷,新舊節點依次比較,遇到key值不匹配的立即中斷遍歷。 第二次遍歷,對剩下的舊節點建立 “key - 節點”的Map表,遍歷剩下的新節點,按key值從表中查找舊節點進行比較。以下是三種case下,新舊節點匹配比較的情況。

React中調和算法Diffing算法策略的示例分析

key值的使用要求

從單節點和數組節點的diffing上看,key值主要是為了減少新建。為了保證diffing時新建舊節點能匹配上,key值使用時有如下注意:

  1. 得穩定,如果key值每次都變化(比如使用了隨機數),diffing時,新舊節全部匹配不上,將會引起大量的新建;

  2. 必須得唯一,如果key值不唯一,在建立“key - 節點”的Map表時,會遺漏和錯亂,導致頁面更新錯誤。

對于單節點,diffing時key值也會用到,不要認為其沒用隨便亂設置。 也有一些不規范的用法,對單節點使用key值來實現組件的銷毀和重建,但這種用法是不符合React的設計理念的。

例如,有一個日志組件,內部拉取日志數據,對外部沒有數據依賴。但是在需求迭代時,在同頁面增加了審批操作,審批后,后端會新增一條日志數據,這時候會希望前端頁面實時的展示新增的日志數據,會需要觸發日志組件重新拉取數據。如果不使用向上提升數據的方式來解決問題,可以給該組件指定一個隨機的key,當審批操作完成時,修改key值,則組件就會重新構建。但這種方式的開銷較高,整個組件樹都會銷毀重建。可以采用其他解決方案代替,例如可以給該組件指定ref,當審批完成后,通過ref調用該組件的刷新函數,重新獲取數據,更新組件。

對于數組節點,key值主要是在子節點位置發生大的錯位時,會起到關鍵作用。 對于普通的末尾新增,和末尾刪除,第一次index遍歷就可以匹配完,不會進入第二次key map的遍歷。 因為key值對“穩定”和“唯一”性這兩個要求,一般前端會需要后端對list數據提供一個唯一標識,對于聚合接口,會給后端增加額外工作,這種情況,可以先了解數據的變化特性,再決定是否真的需要設置key。

對于上面的日志組件,日志是一個列表,新增的日志,都是插在第一行,如果不設置key,基本上所有的子節點都要更新。如果設置key,就需要后端服務為每一條日志增加“永遠”惟一的標識符,例如id。曾經經歷過一次因為key值的唯一性變化,導致數據更新時頁面展示錯誤的案例。

以上是“React中調和算法Diffing算法策略的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

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

AI

百色市| 梨树县| 博兴县| 远安县| 张家川| 青田县| 蒙自县| 英超| 常山县| 江都市| 陵水| 乳山市| 喀喇| 密山市| 新乡市| 麻阳| 灵石县| 汉寿县| 安龙县| 旅游| 临西县| 中阳县| 上杭县| 桐柏县| 博乐市| 澄城县| 达州市| 大埔县| 吉水县| 益阳市| 扬州市| 景宁| 阳朔县| 金湖县| 凌海市| 基隆市| 巫山县| 蒙城县| 亚东县| 明光市| 兴仁县|