虛擬DOM觀察

自從react流行起來(lái)后床蜘,前端開(kāi)發(fā)者們對(duì)虛擬DOM的研究就從未停止過(guò)悠垛,現(xiàn)在開(kāi)源世界里已經(jīng)有了非常多優(yōu)秀的虛擬DOM庫(kù)供大家使用蕾额。虛擬DOM這項(xiàng)技術(shù)能流行起來(lái)大概有三個(gè)原因但荤。

  • 通過(guò)減少真實(shí)DOM操作提高系統(tǒng)運(yùn)行效率
  • 降低維護(hù)狀態(tài) -> 視圖的復(fù)雜程度
  • 幫助開(kāi)發(fā)者輕松實(shí)現(xiàn)前端組件化

一罗岖、虛擬DOM的工作過(guò)程

虛擬DOM以virtual node為基礎(chǔ)單元構(gòu)造虛擬DOM樹(shù),然后隨系統(tǒng)狀態(tài)的變化來(lái)操作真實(shí)DOM腹躁。大致的工作過(guò)程如下:

  1. 創(chuàng)建virtual node桑包,構(gòu)建起虛擬DOM樹(shù)
  2. 根據(jù)虛擬DOM樹(shù)創(chuàng)建真實(shí)DOM樹(shù)
  3. 系統(tǒng)狀態(tài)變化,產(chǎn)生新的虛擬DOM樹(shù)
  4. 拿新樹(shù)與舊樹(shù)做diff操作纺非,分析出兩棵樹(shù)的差異
  5. 針對(duì)差異對(duì)真實(shí)DOM做修改

二哑了、虛擬DOM節(jié)點(diǎn)

虛擬DOM節(jié)點(diǎn)(virtual node)對(duì)應(yīng)真實(shí)DOM中的HTML Element,它的構(gòu)造非常簡(jiǎn)單烧颖,只需要提供標(biāo)簽名弱左,屬性,子節(jié)點(diǎn)和一個(gè)用于區(qū)分兄弟節(jié)點(diǎn)的key炕淮。它的結(jié)構(gòu)和真實(shí)DOM里的元素非常類似拆火。

function VirtualNode(tagName, properties, children, key) {
    this.tagName = tagName
    this.properties = properties || null
    this.children = children || []
    this.key = key != null ? String(key) : undefined
    ...
}

一層一層的virtual node組成了一棵虛擬DOM樹(shù)

三、diff

每棵樹(shù)都有一個(gè)根節(jié)點(diǎn)涂圆,從根節(jié)點(diǎn)做遍歷是分析樹(shù)最快的方式们镜。遍歷的方式可以選擇深度優(yōu)先遍歷或者廣度優(yōu)先遍歷。為了降低diff的復(fù)雜度润歉,一般的虛擬DOM庫(kù)都會(huì)設(shè)置兩個(gè)前提:

  • 類型不同(tagName不同)的兩個(gè)virtual node被認(rèn)為是完全不一樣的模狭,即使它們的所有屬性、子節(jié)點(diǎn)和key都一樣
  • 對(duì)于同一層級(jí)的一組子節(jié)點(diǎn)踩衩,它們可以通過(guò)唯一的 key值進(jìn)行區(qū)分
    接下來(lái)是具體的diff過(guò)程
1.不同類型節(jié)點(diǎn)的對(duì)比

對(duì)于不同類型的兩個(gè)節(jié)點(diǎn)胞皱,反映到真實(shí)DOM上的操作是邪意,直接刪除舊的節(jié)點(diǎn),然后插入新的節(jié)點(diǎn)

2.相同類型節(jié)點(diǎn)的對(duì)比

根據(jù)key值分兩種情況反砌, key值相同的兩個(gè)節(jié)點(diǎn)會(huì)接著比較屬性和子節(jié)點(diǎn)雾鬼,key值不同的情況下,和不同類型節(jié)點(diǎn)一樣宴树,刪除舊的節(jié)點(diǎn)策菜,插入新的節(jié)點(diǎn)。

3.virtual node節(jié)點(diǎn)列表對(duì)比

這里需要強(qiáng)調(diào)的是酒贬,節(jié)點(diǎn)列表里的每一項(xiàng)都沒(méi)有key值的情況下又憨,舊列表中的所有項(xiàng)都不會(huì)被重新利用,反映到真實(shí)DOM節(jié)點(diǎn)就是直接用新的元素列表代替舊的元素列表锭吨,這樣情況沒(méi)有任何可以優(yōu)化的地方蠢莺。所以這里說(shuō)的是每一項(xiàng)帶有唯一key值的virutal node節(jié)點(diǎn)列表之間的對(duì)比。
節(jié)點(diǎn)列表之間的對(duì)比類似于比較兩個(gè)字符串

  A:  [a b c d e f g] 
  B:  [a c b h f e g] 

首先分析出可重用的節(jié)點(diǎn)零如,如a躏将,bc考蕾,e祸憋,fg肖卧,通過(guò)對(duì)比兩個(gè)列表的key值得出一個(gè)新的臨時(shí)列表C蚯窥,在B列表中沒(méi)有的用-1表示,把B列表中存在但A列表不存在的放到最后塞帐。

  C:  [a b c -1 e f g h] 

然后做一下處理拦赠,記錄下值是-1的節(jié)點(diǎn)的索引,這些節(jié)點(diǎn)對(duì)應(yīng)的DOM元素會(huì)被刪除葵姥,在C列表中也刪除-1的值

  C:  [a b c e f g h] 

接下來(lái)同時(shí)遍歷B荷鼠、C兩個(gè)列表,對(duì)比相同位置下的節(jié)點(diǎn)牌里,根據(jù)下面的規(guī)則來(lái)制定出移動(dòng)真實(shí)DOM元素次數(shù)最少的步驟颊咬。

  • 值相同务甥,對(duì)應(yīng)的真實(shí)DOM不移動(dòng)牡辽,如a節(jié)點(diǎn)
  • 值不同,記錄下當(dāng)前索引敞临,把C列表中的節(jié)點(diǎn)也記錄下來(lái)态辛,它對(duì)應(yīng)的DOM元素會(huì)被插入到剛才記錄下的索引處,如c會(huì)被插入到列表第二的位置
    最后挺尿,得到兩個(gè)列表對(duì)比的分析結(jié)果

四奏黑、把差異應(yīng)用到真正的DOM樹(shù)上

和diff過(guò)程采用的遍歷方式一樣炊邦,遍歷一次整個(gè)真實(shí)DOM樹(shù),最后根據(jù)記錄的差異來(lái)操作DOM元素熟史。

五馁害、小結(jié)

本文大致講解了虛擬DOM的工作過(guò)程和Diff原理,參考的是virtual-dom這個(gè)虛擬DOM庫(kù)蹂匹,同時(shí)我自己用這個(gè)庫(kù)實(shí)現(xiàn)了一個(gè)todo-list應(yīng)用 todolist-virtualdom
碘菜,幫助大家理解虛擬DOM的使用方法和工作過(guò)程。

參考資料

深度剖析:如何實(shí)現(xiàn)一個(gè) Virtual DOM 算法
深入淺出 React(四):虛擬 DOM Diff 算法解析
Reconciliation

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末限寞,一起剝皮案震驚了整個(gè)濱河市忍啸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌履植,老刑警劉巖计雌,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異玫霎,居然都是意外死亡凿滤,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門鼠渺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)鸭巴,“玉大人,你說(shuō)我怎么就攤上這事拦盹【樽妫” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵普舆,是天一觀的道長(zhǎng)恬口。 經(jīng)常有香客問(wèn)我,道長(zhǎng)沼侣,這世上最難降的妖魔是什么祖能? 我笑而不...
    開(kāi)封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮蛾洛,結(jié)果婚禮上养铸,老公的妹妹穿的比我還像新娘。我一直安慰自己轧膘,他們只是感情好钞螟,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著谎碍,像睡著了一般鳞滨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蟆淀,一...
    開(kāi)封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天拯啦,我揣著相機(jī)與錄音澡匪,去河邊找鬼。 笑死褒链,一個(gè)胖子當(dāng)著我的面吹牛唁情,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播甫匹,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼荠瘪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了赛惩?” 一聲冷哼從身側(cè)響起哀墓,我...
    開(kāi)封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎喷兼,沒(méi)想到半個(gè)月后篮绰,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡季惯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年吠各,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片勉抓。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡贾漏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出藕筋,到底是詐尸還是另有隱情纵散,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布隐圾,位于F島的核電站伍掀,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏暇藏。R本人自食惡果不足惜蜜笤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望盐碱。 院中可真熱鬧把兔,春花似錦、人聲如沸瓮顽。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)趣倾。三九已至聘惦,卻和暖如春某饰,著一層夾襖步出監(jiān)牢的瞬間儒恋,已是汗流浹背善绎。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诫尽,地道東北人禀酱。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像牧嫉,于是被迫代替她去往敵國(guó)和親剂跟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

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

  • 步驟一:探索你的家庭是什么樣的酣藻? 1曹洽、 兩個(gè)人的家庭使命宣言 如果你的家中目前只有你和你的配偶,去一個(gè)你們兩個(gè)可以...
    zhanghr55閱讀 8,840評(píng)論 0 0
  • 君生我未生辽剧,我生君已老送淆,君恨我生遲,我恨君生早!彼有死境怕轿,魂之歸路偷崩,足八百里 無(wú)花無(wú)葉,黃沙遍地 延綿流漣撞羽,故名黃...
    青松玥冷閱讀 377評(píng)論 0 0
  • First created on Oct.12.2013. All rights reserved. 懷古傷秋從來(lái)...
    astrocachet閱讀 456評(píng)論 0 0
  • 青春就像小酒桌 醉生夢(mèng)死就是喝 龍蝦海參鴻門宴 紅白啤酒齊上陣 喝了這頓整下頓 誰(shuí)不斤八別下桌 稱兄道弟嘮神嗑 扶...
    俗人糖糖閱讀 192評(píng)論 0 1