vue之補充虛擬Dom(十二)

一狡逢、虛擬Dom簡介

虛擬Dom的最初出現(xiàn)是在Rect中逻谦,性能卓越

二刷晋、什么是虛擬Dom?

vdom可以看作是一個使用javascript模擬了DOM結構的樹形結構矢否,這個樹結構包含整個DOM結構的信息仲闽,如以下代碼:

//原始html結構
<ul class="list">
      <li class="child">child1</li>
      <li class="child">child2</li>
</ul
//虛擬Dom結構
{
   tag:"ul",
   attrs:{
       className:"list"
   },
  children:[
   {
       tag:"li",
       attrs:{
           className:"child"
       },
      children:["child1"]
  }, {
       tag:"li",
       attrs:{
           className:"child"
       },
      children:["child2"]
  }
]

}

可見上方的DOM結構,不論是標簽名稱還是標簽的屬性或標簽的子集僵朗,都會對應在下邊的樹結構里蔼囊。

三、為什么需要虛擬DOM衣迷,它有什么好處?

Web界面由DOM樹(樹的意思是數(shù)據(jù)結構)來構建畏鼓,當其中一部分發(fā)生變化時,其實就是對應某個DOM節(jié)點發(fā)生了變化壶谒,
虛擬DOM就是為了解決瀏覽器性能問題而被設計出來的云矫。如前,若一次操作中有10次更新DOM的動作汗菜,虛擬DOM不會立即操作DOM让禀,而是將這10次更新的diff內(nèi)容保存到本地一個JS對象中,最終將這個JS對象一次性attch到DOM樹上陨界,再進行后續(xù)操作巡揍,避免大量無謂的計算量。所以菌瘪,用JS對象模擬DOM節(jié)點的好處是腮敌,頁面的更新可以先全部反映在JS對象(虛擬DOM)上阱当,操作內(nèi)存中的JS對象的速度顯然要更快,等更新完成后糜工,再將最終的JS對象映射成真實的DOM弊添,交由瀏覽器去繪制。
<1>具備跨平臺的優(yōu)勢

由于 Virtual DOM 是以 JavaScript 對象為基礎而不依賴真實平臺環(huán)境捌木,所以使它具有了跨平臺的能力油坝,比如說瀏覽器平臺、Weex刨裆、Node 等澈圈。

(2)操作 DOM 慢,js運行效率高帆啃。我們可以將DOM對比操作放在JS層极舔,提高效率。

因為DOM操作的執(zhí)行速度遠不如Javascript的運算速度快链瓦,因此,把大量的DOM操作搬運到Javascript中盯桦,運用patching算法來計算出真正需要更新的節(jié)點慈俯,最大限度地減少DOM操作,從而顯著提高性能拥峦。
Virtual DOM 本質上就是在 JS 和 DOM 之間做了一個緩存贴膘。可以類比 CPU 和硬盤略号,既然硬盤這么慢刑峡,我們就在它們之間加個緩存:既然 DOM 這么慢,我們就在它們 JS 和 DOM 之間加個緩存玄柠。CPU(JS)只操作內(nèi)存(Virtual DOM)突梦,最后的時候再把變更寫入硬盤(DOM)

(3)提升渲染性能
Virtual DOM的優(yōu)勢不在于單次的操作,而是在大量羽利、頻繁的數(shù)據(jù)更新下宫患,能夠對視圖進行合理、高效的更新这弧。

為了實現(xiàn)高效的DOM操作娃闲,一套高效的虛擬DOM diff算法顯得很有必要。我們通過patch 的核心----diff 算法匾浪,找出本次DOM需要更新的節(jié)點來更新皇帮,其他的不更新。比如修改某個model 100次蛋辈,從1加到100属拾,那么有了Virtual DOM的緩存之后,只會把最后一次修改patch到view上。那diff 算法的實現(xiàn)過程是怎樣的捌年?
diff算法


image

Vue的diff算法是基于snabbdom改造過來的瓢娜,僅在同級的vnode間做diff,遞歸地進行同級vnode的diff礼预,最終實現(xiàn)整個DOM樹的更新眠砾。因為跨層級的操作是非常少的,忽略不計托酸,這樣時間復雜度就從O(n3)變成O(n)褒颈。
diff 算法包括幾個步驟:
用 JavaScript 對象結構表示 DOM 樹的結構;然后用這個樹構建一個真正的 DOM 樹励堡,插到文檔當中
當狀態(tài)變更的時候谷丸,重新構造一棵新的對象樹。然后用新的樹和舊的樹進行比較应结,記錄兩棵樹差異
把所記錄的差異應用到所構建的真正的DOM樹上刨疼,視圖就更新了

四、diff 算法的實現(xiàn)過程

diff 算法本身非常復雜鹅龄,實現(xiàn)難度很大揩慕。本文去繁就簡,粗略介紹以下兩個核心函數(shù)實現(xiàn)流程:

patch(container,vnode) :初次渲染的時候扮休,將VDOM渲染成真正的DOM然后插入到容器里面迎卤。
patch(vnode,newVnode):再次渲染的時候,將新的vnode和舊的vnode相對比玷坠,然后之間差異應用到所構建的真正的DOM樹上蜗搔。

  1. patch(container,vnode)
    通過這個函數(shù)可以讓VNode渲染成真正的DOM,我們通過以下模擬代碼八堡,可以了解大致過程:
function createElement(vnode) {    
var tag = vnode.tag  
var attrs = vnode.attrs || {}    
var children = vnode.children || []    
if (!tag) {       
 return null  
  }    
// 創(chuàng)建真實的 DOM 元素    
var elem = document.createElement(tag)   
 // 屬性    
var attrName    
for (attrName in attrs) {    
    if (attrs.hasOwnProperty(attrName)) { 
           // 給 elem 添加屬性
           elem.setAttribute(attrName, attrs[attrName])
        }
    }
    // 子元素
    children.forEach(function (childVnode) {
        // 給 elem 添加子元素樟凄,如果還有子節(jié)點,則遞歸的生成子節(jié)點兄渺。
        elem.appendChild(createElement(childVnode))  // 遞歸
    })    // 返回真實的 DOM 元素   
 return elem
}
  1. patch(vnode,newVnode)
//考慮新舊節(jié)點對比的情況
function updateChildren(vnode, newVnode) {
    var children = vnode.children || []
    var newChildren = newVnode.children || []
  // 遍歷現(xiàn)有的children
    children.forEach(function (childVnode, index) {
        var newChildVnode = newChildren[index]
  // 兩者tag一樣
        if (childVnode.tag === newChildVnode.tag) {
            // 深層次對比不同,遞歸
            updateChildren(childVnode, newChildVnode)
        } else { 
  // 兩者tag不一樣
           replaceNode(childVnode, newChildVnode) 
       }
    }
)}

如果感覺有幫助,請留下一個寶貴的贊或者給小編一個贊賞H茉拧6铡!

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末凳兵,一起剝皮案震驚了整個濱河市百新,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌庐扫,老刑警劉巖饭望,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仗哨,死亡現(xiàn)場離奇詭異,居然都是意外死亡铅辞,警方通過查閱死者的電腦和手機厌漂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來斟珊,“玉大人苇倡,你說我怎么就攤上這事《诓龋” “怎么了旨椒?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長堵漱。 經(jīng)常有香客問我综慎,道長,這世上最難降的妖魔是什么勤庐? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任示惊,我火速辦了婚禮,結果婚禮上愉镰,老公的妹妹穿的比我還像新娘米罚。我一直安慰自己,他們只是感情好岛杀,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著崭孤,像睡著了一般类嗤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辨宠,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天遗锣,我揣著相機與錄音,去河邊找鬼嗤形。 笑死精偿,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的赋兵。 我是一名探鬼主播笔咽,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼霹期!你這毒婦竟也來了叶组?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤历造,失蹤者是張志新(化名)和其女友劉穎甩十,沒想到半個月后船庇,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡侣监,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年鸭轮,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片橄霉。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡窃爷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出酪劫,到底是詐尸還是另有隱情吞鸭,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布覆糟,位于F島的核電站刻剥,受9級特大地震影響,放射性物質發(fā)生泄漏滩字。R本人自食惡果不足惜造虏,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望麦箍。 院中可真熱鬧漓藕,春花似錦、人聲如沸挟裂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诀蓉。三九已至栗竖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間渠啤,已是汗流浹背狐肢。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留沥曹,地道東北人份名。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像妓美,于是被迫代替她去往敵國和親僵腺。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

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

  • 前言 ??Vue2.0引入了虛擬DOM壶栋,比Vue1.0的初始渲染速度提升了2~4倍想邦,并大大降低了內(nèi)存消耗。目前主流...
    A鄭家慶閱讀 13,412評論 0 10
  • 摘要: 什么是虛擬DOM? 作者:浪里行舟 Fundebug經(jīng)授權轉載委刘,版權歸原作者所有丧没。 前言 Vue.js 2...
    Fundebug閱讀 7,411評論 0 6
  • 寫在前面 這篇文章算是對最近寫的一系列Vue.js源碼的文章(https://github.com/answers...
    染陌同學閱讀 2,136評論 0 14
  • 風吹過詩人的指縫雨落在流浪者的胸膛星光灑在孩子的眼瞳黑夜試圖掩蓋城市的骯臟于這無名之路 予我踽踽獨行...
    路修遠a閱讀 246評論 1 4
  • 本來以為下定決心這寫點東西的鹰椒,但隔了一個星期還是什么也沒寫出來∨煌總是以各種理由說自己沒時間漆际,今夜是難得的獨處之夜。...
    水田wxh閱讀 189評論 0 0