欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React 的調(diào)和算法Diffing 算法策略詳解

 更新時(shí)間:2021年12月29日 11:30:51   作者:秋墨江雪  
React的調(diào)和算法,主要發(fā)生在render階段,調(diào)和算法并不是一個(gè)特定的算法函數(shù),而是指在調(diào)和過程中,為提高構(gòu)建workInProcess樹的性能,以及Dom樹更新的性能,而采用的一種策略,又稱diffing算法

算法策略

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

只比較同層級(jí)的節(jié)點(diǎn),(貌似這一點(diǎn)沒有在官網(wǎng)中提到)

對(duì)于單節(jié)點(diǎn)比較,如果當(dāng)前節(jié)點(diǎn)type 和 key 不相同,不再比較其下子節(jié)點(diǎn),直接刪掉該節(jié)點(diǎn)及其下整棵子樹,根據(jù)ReactElement重新生成節(jié)點(diǎn)樹。因?yàn)镽eact認(rèn)為不同類型的組件生成的樹形結(jié)構(gòu)不一樣,不必復(fù)用。

如果子節(jié)點(diǎn)是數(shù)組,可根據(jù)唯一的key值定位節(jié)點(diǎn)進(jìn)行比較,這樣即使子節(jié)點(diǎn)順序發(fā)生變化,也可以根據(jù)key值進(jìn)行復(fù)用。

值得注意的是,所有節(jié)點(diǎn)的diffing都會(huì)比較key,key 默認(rèn)值為null。若是沒有設(shè)置,則null是恒等于null的,認(rèn)為key是相同的。

單節(jié)點(diǎn)diffing

單個(gè)節(jié)點(diǎn)進(jìn)行diffing時(shí),會(huì)diffing兩組屬性:fibe.elementType vs ReactElement.type , fibe.key vs ReactElement.key, 如果這兩組屬性都相等,數(shù)據(jù)結(jié)構(gòu)的物理空間會(huì)有如下復(fù)用邏輯(詳見源碼reconcileSingleElement函數(shù)):

  1. 如果current fibe 存在 alternate 節(jié)點(diǎn),(這意味著這個(gè)fibe節(jié)點(diǎn)之前參與過調(diào)和),則復(fù)用該alternate節(jié)點(diǎn)的物理空間;否則需要clone current fibe節(jié)點(diǎn),占用新的物理空間
  2. 對(duì)應(yīng)的instance 或者 Dom 會(huì)被復(fù)用
  3. current fibe 下的child樹也會(huì)被直接掛載過來(下一步遞歸子節(jié)點(diǎn)時(shí),會(huì)被使用)

如果兩組屬性有一個(gè)不相等:

  • fibe 根據(jù)ReactElement重新創(chuàng)建
  • 對(duì)應(yīng)的instance和Dom 也會(huì)重建
  • child 樹全部刪除。

如果生成的ReactElement 是單節(jié)點(diǎn),但是對(duì)應(yīng)的current樹上是多節(jié)點(diǎn)時(shí),會(huì)從逐一查找有沒有匹配的,找到匹配的,其他的都刪除;找不到,全部刪除。例如Couter組件有如下邏輯:當(dāng)點(diǎn)擊次數(shù)大于10時(shí),隱藏點(diǎn)擊按鈕。當(dāng)?shù)竭_(dá)第10次時(shí),span節(jié)點(diǎn)會(huì)被復(fù)用。

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}>點(diǎn)擊</button>
            <span>點(diǎn)擊次數(shù):{this.state.count}</span>
        ]:<span>點(diǎn)擊次數(shù):{this.state.count}</span>;
    }
}

數(shù)組節(jié)點(diǎn)diffing

數(shù)組節(jié)點(diǎn)進(jìn)行diffing時(shí),流程比較復(fù)雜:(源碼見reconcileChildrenArray函數(shù))

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

key值的使用要求

從單節(jié)點(diǎn)和數(shù)組節(jié)點(diǎn)的diffing上看,key值主要是為了減少新建。為了保證diffing時(shí)新建舊節(jié)點(diǎn)能匹配上,key值使用時(shí)有如下注意:

  1. 得穩(wěn)定,如果key值每次都變化(比如使用了隨機(jī)數(shù)),diffing時(shí),新舊節(jié)全部匹配不上,將會(huì)引起大量的新建;
  2. 必須得唯一,如果key值不唯一,在建立“key - 節(jié)點(diǎn)”的Map表時(shí),會(huì)遺漏和錯(cuò)亂,導(dǎo)致頁面更新錯(cuò)誤。

對(duì)于單節(jié)點(diǎn),diffing時(shí)key值也會(huì)用到,不要認(rèn)為其沒用隨便亂設(shè)置。 也有一些不規(guī)范的用法,對(duì)單節(jié)點(diǎn)使用key值來實(shí)現(xiàn)組件的銷毀和重建,但這種用法是不符合React的設(shè)計(jì)理念的。

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

對(duì)于數(shù)組節(jié)點(diǎn),key值主要是在子節(jié)點(diǎn)位置發(fā)生大的錯(cuò)位時(shí),會(huì)起到關(guān)鍵作用。 對(duì)于普通的末尾新增,和末尾刪除,第一次index遍歷就可以匹配完,不會(huì)進(jìn)入第二次key map的遍歷。 因?yàn)閗ey值對(duì)“穩(wěn)定”和“唯一”性這兩個(gè)要求,一般前端會(huì)需要后端對(duì)list數(shù)據(jù)提供一個(gè)唯一標(biāo)識(shí),對(duì)于聚合接口,會(huì)給后端增加額外工作,這種情況,可以先了解數(shù)據(jù)的變化特性,再?zèng)Q定是否真的需要設(shè)置key。

對(duì)于上面的日志組件,日志是一個(gè)列表,新增的日志,都是插在第一行,如果不設(shè)置key,基本上所有的子節(jié)點(diǎn)都要更新。如果設(shè)置key,就需要后端服務(wù)為每一條日志增加“永遠(yuǎn)”惟一的標(biāo)識(shí)符,例如id。曾經(jīng)經(jīng)歷過一次因?yàn)閗ey值的唯一性變化,導(dǎo)致數(shù)據(jù)更新時(shí)頁面展示錯(cuò)誤的案例。

到此這篇關(guān)于React 的調(diào)和算法(Diffing 算法)的文章就介紹到這了,更多相關(guān)React Diffing 算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • react 權(quán)限樹形結(jié)構(gòu)實(shí)現(xiàn)代碼

    react 權(quán)限樹形結(jié)構(gòu)實(shí)現(xiàn)代碼

    這篇文章主要介紹了react 權(quán)限樹形結(jié)構(gòu)實(shí)現(xiàn)代碼,項(xiàng)目背景react + ant design,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2024-05-05
  • React優(yōu)雅的封裝SvgIcon組件示例

    React優(yōu)雅的封裝SvgIcon組件示例

    這篇文章主要為大家介紹了React優(yōu)雅的封裝SvgIcon組件示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • React中的ref屬性的使用示例詳解

    React中的ref屬性的使用示例詳解

    React 提供了 refrefref 屬性,讓我們可以引用組件的實(shí)例或者原生 DOM 元素,使用 refrefref,可以在父組件中調(diào)用子組件暴露出來的方法,或者調(diào)用原生 element 的 API,這篇文章主要介紹了React中的ref屬性的使用,需要的朋友可以參考下
    2023-04-04
  • 在Create React App中啟用Sass和Less的方法示例

    在Create React App中啟用Sass和Less的方法示例

    這篇文章主要介紹了在Create React App中啟用Sass和Less的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-01-01
  • react native 原生模塊橋接的簡單說明小結(jié)

    react native 原生模塊橋接的簡單說明小結(jié)

    這篇文章主要介紹了react native 原生模塊橋接的簡單說明小結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • React 高階組件HOC用法歸納

    React 高階組件HOC用法歸納

    高階組件就是接受一個(gè)組件作為參數(shù)并返回一個(gè)新組件(功能增強(qiáng)的組件)的函數(shù)。這里需要注意高階組件是一個(gè)函數(shù),并不是組件,這一點(diǎn)一定要注意,本文給大家分享React 高階組件HOC使用小結(jié),一起看看吧
    2021-06-06
  • React?Hooks的useState、useRef使用小結(jié)

    React?Hooks的useState、useRef使用小結(jié)

    React Hooks 是 React 16.8 版本引入的新特性,useState和useRef是兩個(gè)常用的Hooks,本文主要介紹了React?Hooks的useState、useRef使用,感興趣的可以了解一下
    2024-01-01
  • React中使用TS完成父組件調(diào)用子組件的操作方法

    React中使用TS完成父組件調(diào)用子組件的操作方法

    由于在項(xiàng)目開發(fā)過程中,我們往往時(shí)需要調(diào)用子組件中的方法,這篇文章主要介紹了React中使用TS完成父組件調(diào)用子組件,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • mobx在react hooks中的應(yīng)用方式

    mobx在react hooks中的應(yīng)用方式

    這篇文章主要介紹了mobx在react hooks中的應(yīng)用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • 關(guān)于getDerivedStateFromProps填坑記錄

    關(guān)于getDerivedStateFromProps填坑記錄

    這篇文章主要介紹了關(guān)于getDerivedStateFromProps填坑記錄,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06

最新評(píng)論