React Native填坑之旅--Diff算法(番外篇)

使用React或者RN開(kāi)發(fā)APP如果不知道Diff算法的話簡(jiǎn)直是說(shuō)不過(guò)去啊。畢竟“知其然,知其所以然”這句老話從遠(yuǎn)古喊到現(xiàn)代了。

以下內(nèi)容基本是官網(wǎng)文章的一個(gè)總結(jié)残拐、壓縮。這次要謙虛一下碟嘴,畢竟深入研究RN的時(shí)間不多溪食,如果有什么理解的不對(duì)的地方還請(qǐng)各位讀者指正。

用React官網(wǎng)的Thinking in React作為例子娜扇。

這幾個(gè)組件的結(jié)構(gòu)是這樣的:

FilterableProductTable
    SearchBar

    ProductTable
        ProductCategoryRow

        ProductRow

相關(guān)代碼错沃,省去不必要的以后是這樣的:

class ProductCategoryRow extends React.Comonent {
  render() {
    return (<tr><th colSpan="2">{this.props.category}</th></tr>);
  }
};

class ProductRow extends React.Component{
  render() {
    return (
      <tr>
        <td>{name}</td>
        <td>{this.props.product.price}</td>
      </tr>
    );
  }
};

class ProductTable extends React.Component {
  render() {
    return (
      <table>
        <tbody>{rows}</tbody>
      </table>
    );
  }
};

class SearchBar extends React.Component{
  render() {
    return (
      <form>
        //...略...
      </form>
    );
  }
};

class FilterableProductTable extends React.Component{
  render() {
    return (
      <div>
        <SearchBar />
        <ProductTable products={this.props.products} />
      </div>
    );
  }
};
 
ReactDOM.render(
  <FilterableProductTable products={PRODUCTS} />,
  document.getElementById('container')
);

上面的例子說(shuō)明React的組件最后組成了一個(gè)樹(shù)形結(jié)構(gòu)。在React繪制的時(shí)候雀瓢,會(huì)在內(nèi)存里對(duì)應(yīng)每一個(gè)組件建立一個(gè)節(jié)點(diǎn)枢析,并最終形成一個(gè)和組件樹(shù)結(jié)構(gòu)一樣的樹(shù)。我們就叫這個(gè)樹(shù)叫影子樹(shù)(這個(gè)叫法不是出自官方)刃麸。我們可以理解為這個(gè)影子樹(shù)包含了React App組建的結(jié)構(gòu)和一些屬性值醒叁。

在組件發(fā)生變化的時(shí)候(一般是調(diào)用了setState),React會(huì)形成一個(gè)影子樹(shù)二號(hào)。然后對(duì)比影子樹(shù)1號(hào)和影子樹(shù)2號(hào)的不同把沼。

我們知道對(duì)比兩個(gè)樹(shù)的最小不同的時(shí)間復(fù)雜度是O(n3
)啊易,n是樹(shù)里的節(jié)點(diǎn)數(shù)。這個(gè)復(fù)雜度下饮睬,稍有量級(jí)的應(yīng)用都會(huì)遇到一個(gè)問(wèn)題:無(wú)法忽略的慢租谈。于是,F(xiàn)B的同學(xué)們使用了更加高效的啟發(fā)式算法捆愁,把復(fù)雜度降低到了O(n)割去。

但是,不管是什么算法最后都需要對(duì)比兩個(gè)節(jié)點(diǎn)的不同昼丑。有三種情況需要考慮:

一劫拗、節(jié)點(diǎn)之間的比較

節(jié)點(diǎn),英語(yǔ)里的Node矾克,包括兩種類型:一個(gè)是React組件,一個(gè)是HTML的DOM憔足。下文也是同樣的含義胁附。

節(jié)點(diǎn)類型不同

如果是HTML DOM不同的話,直接使用新的替換舊的滓彰。

如果是組件類型不同的話也直接使用新的替換舊的控妻。

HTML DOM類型相同

在React里樣式并不是一個(gè)純粹的字符串,而是一個(gè)對(duì)象揭绑,這樣的話在樣式發(fā)生改變的時(shí)候只需要改變替換變化以后的樣式弓候。修改完當(dāng)前節(jié)點(diǎn)之后,遞歸處理該節(jié)點(diǎn)的子節(jié)點(diǎn)他匪。

組件類型相同

組件類型相同的菇存,使用React機(jī)制處理。一般是使用新的props替換掉舊的props邦蜜,并在之后調(diào)用組件的componentWill/DidReceiveProps方法依鸥,之前的組件的render方法會(huì)被調(diào)用。節(jié)點(diǎn)的比較機(jī)制開(kāi)始遞歸作用于這個(gè)它的子節(jié)點(diǎn)上悼沈。

二贱迟、兩個(gè)列表之間的比較

一列節(jié)點(diǎn)中的一個(gè)發(fā)生了改變,React并沒(méi)有什么好方法來(lái)處理這個(gè)問(wèn)題絮供。循環(huán)新舊兩個(gè)列表衣吠,并找出不同是React唯一的處理方法。

但是壤靶,有一個(gè)可以把這個(gè)算法的復(fù)雜度降低的辦法缚俏。那就是我們?cè)谏梢涣泄?jié)點(diǎn)的時(shí)候給每一個(gè)節(jié)點(diǎn)上添加一個(gè)key。這個(gè)key只需要在這一列節(jié)點(diǎn)中唯一,不需要全局唯一袍榆。

三胀屿、取舍

需要注意的是,上面的啟發(fā)式算法是基于兩點(diǎn)假設(shè):
*類型想聽(tīng)的節(jié)點(diǎn)總是生成同樣的樹(shù)包雀,而類型不同的節(jié)點(diǎn)也總是生成不同的樹(shù)宿崭。
*可以為多次render都表現(xiàn)穩(wěn)定的節(jié)點(diǎn)設(shè)置key。

上面的節(jié)點(diǎn)之間的比較算法基本就是基于這兩個(gè)假設(shè)而實(shí)現(xiàn)的才写。也就是要提高React應(yīng)用的效率葡兑,需要我們按照這兩點(diǎn)假設(shè)來(lái)開(kāi)發(fā)

否則赞草,React會(huì)重獲整個(gè)APP讹堤。那就是噩夢(mèng)一樣的情況了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末厨疙,一起剝皮案震驚了整個(gè)濱河市洲守,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌沾凄,老刑警劉巖梗醇,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異撒蟀,居然都是意外死亡叙谨,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門保屯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)手负,“玉大人,你說(shuō)我怎么就攤上這事姑尺【怪眨” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵股缸,是天一觀的道長(zhǎng)衡楞。 經(jīng)常有香客問(wèn)我,道長(zhǎng)敦姻,這世上最難降的妖魔是什么瘾境? 我笑而不...
    開(kāi)封第一講書人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮镰惦,結(jié)果婚禮上迷守,老公的妹妹穿的比我還像新娘。我一直安慰自己旺入,他們只是感情好兑凿,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布凯力。 她就那樣靜靜地躺著,像睡著了一般礼华。 火紅的嫁衣襯著肌膚如雪咐鹤。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,521評(píng)論 1 304
  • 那天圣絮,我揣著相機(jī)與錄音祈惶,去河邊找鬼。 笑死扮匠,一個(gè)胖子當(dāng)著我的面吹牛捧请,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播棒搜,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼疹蛉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了力麸?” 一聲冷哼從身側(cè)響起可款,我...
    開(kāi)封第一講書人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎克蚂,沒(méi)想到半個(gè)月后筑舅,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡陨舱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了版仔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片游盲。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蛮粮,靈堂內(nèi)的尸體忽然破棺而出益缎,到底是詐尸還是另有隱情,我是刑警寧澤然想,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布莺奔,位于F島的核電站,受9級(jí)特大地震影響变泄,放射性物質(zhì)發(fā)生泄漏令哟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一妨蛹、第九天 我趴在偏房一處隱蔽的房頂上張望屏富。 院中可真熱鬧,春花似錦蛙卤、人聲如沸狠半。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)神年。三九已至已维,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間已日,已是汗流浹背垛耳。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留捂敌,地道東北人艾扮。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像占婉,于是被迫代替她去往敵國(guó)和親泡嘴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 參考文章:深度剖析:如何實(shí)現(xiàn)一個(gè)Virtual DOM 算法 作者:戴嘉華React中一個(gè)沒(méi)人能解釋清楚的問(wèn)題——...
    waka閱讀 5,965評(píng)論 0 21
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,133評(píng)論 25 707
  • 原教程內(nèi)容詳見(jiàn)精益 React 學(xué)習(xí)指南逆济,這只是我在學(xué)習(xí)過(guò)程中的一些閱讀筆記酌予,個(gè)人覺(jué)得該教程講解深入淺出,比目前大...
    leonaxiong閱讀 2,835評(píng)論 1 18
  • 使用React或者RN開(kāi)發(fā)APP如果不知道Diff算法的話簡(jiǎn)直是說(shuō)不過(guò)去啊奖慌。畢竟“知其然抛虫,知其所以然”這句老話從遠(yuǎn)...
    uncle_charlie閱讀 469評(píng)論 0 0
  • 文|水清心寧 2005年夏,我女兒出生简僧。因?yàn)槲覑?ài)人妊高癥并發(fā)產(chǎn)后出血建椰,在醫(yī)院的兩個(gè)多月里,先是婦產(chǎn)科然后內(nèi)分秘科最...
    水清心寧閱讀 3,623評(píng)論 87 121