初探Virtual dom & diff算法

問:
Virtual dom 是什么雳旅?為何會(huì)存在Virtual dom?
答:
用JS模擬DOM結(jié)構(gòu)墩弯。原因:
1.DOM操作是昂貴的,將DOM對(duì)比放在JS層苗分,JS運(yùn)行效率高
2.需要盡量減少DOM操作

我們通過個(gè)小例子來看什么是用JS模擬DOM結(jié)構(gòu):

<ul id=‘list’>
    <li class=‘item’>Item 1 </li>
    <li class=‘item’>Item 2 </li>
</ul>
====>通過某種方法將上面的html代碼轉(zhuǎn)為js對(duì)象
{
    tag: ‘ul’,
    attires: {id: ‘list’},
    children: [
        {
            tag: ‘li’,
            attires: {className: ‘item’},
            children: [‘Item1']
        },
        {
            tag: ‘li’,
            attires: {className: ‘item’},
            children: [‘Item2']
        },
    ]
}

問:
vdom如何使用正驻,核心函數(shù)是什么弊攘?
答:
snabbdom是virtual dom的一種實(shí)現(xiàn)庫,附上github地址https://github.com/snabbdom/snabbdom

核心API

  • h(‘<標(biāo)簽名>’, {…屬性…}, […子元素…])
  • h(‘<標(biāo)簽名>’, {…屬性…}, '...')
  • patch(container, vnode) =》 將vnode渲染在頁面上 初次渲染
  • patch(vnode, newVnode) => rerender update

h函數(shù)可以生成vnode節(jié)點(diǎn)姑曙,這塊跟react解析jsx(React.createElement方法)很像襟交,都是生成vnode。h函數(shù)的傳參渣磷,第一個(gè)參數(shù)是標(biāo)簽名。第二個(gè)是此標(biāo)簽上的屬性授瘦,比如style, class, 事件等醋界。第三個(gè)是children,如果標(biāo)簽下面沒有子元素只有顯示文字的話只需傳字符串就可以了提完,但如果有子元素的話還需要第三個(gè)參數(shù)傳入子元素的vnode同樣使用h函數(shù)生成形纺。
而patch函數(shù)有兩種,一個(gè)是在初次渲染時(shí)調(diào)用徒欣,傳參分別是container元素和生成的vnode逐样。第二種是在頁面更新時(shí)re-render時(shí)調(diào)用,傳參分別是舊的vnode和生成的新的newVnode打肝。

具體看以下的代碼例子:

// 構(gòu)建一個(gè)虛擬節(jié)點(diǎn)脂新,h函數(shù)做的事情可以理解為上面所轉(zhuǎn)化的js對(duì)象
var vnode = h(‘ul#list’, {}, [
        h(‘li.item’, {}, ‘Item1’),
        h(‘li.item’, {}, ‘Item2’),
    ])

// 真實(shí)構(gòu)建一個(gè)container
var container = document.getElementById(‘container’)

// 把vnode渲染進(jìn)空的container容器中
patch(container, vnode)

// 模擬點(diǎn)擊button改變值
var btnChange = document.getElementById(‘btn-change’)
btnChange.addEventListener(‘click’, function(){

    // 構(gòu)建新的虛擬節(jié)點(diǎn),數(shù)字不一樣
    var newVnode = h(‘ul#list’, {}, [
        h(‘li.item’, {}, ‘Item1’),
        h(‘li.item’, {}, ‘ItemB’),
        h(‘li.item’, {}, ‘Item3’),
    ])

    // 將舊的節(jié)點(diǎn)和新的節(jié)點(diǎn)傳入patch函數(shù)粗梭,patch會(huì)diff算法計(jì)算實(shí)際改變的地方并只渲染dom改動(dòng)點(diǎn)
    patch(vnode, newVnode)
})

問:
介紹一下diff算法
答:

  • diff算法是linux的基礎(chǔ)命令
  • vdom中應(yīng)用diff算法是為了找出需要更新的節(jié)點(diǎn)
  • 實(shí)現(xiàn):patch(container, vnode)和patch(vnode, newVnode)
  • 核心邏輯:createElement和updateChildren

我們來看patch(container, vnode) 的核心邏輯代碼(簡寫):

function createElement(vnode) {
    var tag = vnode.tag
    var attires = vnode.attrs || {}
    var children = vnode.children || []

    if (!tag) {
        return null
    }

    // 創(chuàng)建元素
    var elem = document.createElement(tag)
    // 屬性
    var attrName
    for (attrName in attrs) {
        if(attrs.hasOwnProperty(attrName)) {
            elem.setAttribute(attrName, attrs[attrName])
        }
    }
    //子元素
    children.forEach(function(childVnode) {
        // 遞歸調(diào)用 createElement 創(chuàng)建子元素
        elem.appendChild(createElement(childVnode))
    })

    return elem
}

再來看patch(vnode, newVnode)的核心邏輯代碼争便,同樣是簡寫。断医。

function updateChildren(vnode, newVnode){
    var children = vnode.children || []
    var newChildren = newVnode.children || []

    // 遍歷現(xiàn)有的children
    children.forEach(function(child, index){
        var newChild = newChildren[index]
        if(newChild == null){
            return
        }
        if(child.tag === newChild.tag){
            //兩者tag一樣
            updateChildren(child, newChild)
        } else {
            replaceNode(child, newChild)
        }
    })
}

PS: diff算法需要考慮的地方

  • 節(jié)點(diǎn)新增和刪除
  • 節(jié)點(diǎn)重新排序
  • 節(jié)點(diǎn)屬性滞乙,樣式奏纪,事件綁定
  • 如何極致壓榨性能
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市斩启,隨后出現(xiàn)的幾起案子序调,更是在濱河造成了極大的恐慌,老刑警劉巖兔簇,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件发绢,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡男韧,警方通過查閱死者的電腦和手機(jī)朴摊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來此虑,“玉大人甚纲,你說我怎么就攤上這事‰埃” “怎么了介杆?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長韭寸。 經(jīng)常有香客問我春哨,道長,這世上最難降的妖魔是什么恩伺? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任赴背,我火速辦了婚禮,結(jié)果婚禮上晶渠,老公的妹妹穿的比我還像新娘凰荚。我一直安慰自己,他們只是感情好褒脯,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布便瑟。 她就那樣靜靜地躺著,像睡著了一般番川。 火紅的嫁衣襯著肌膚如雪到涂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天颁督,我揣著相機(jī)與錄音践啄,去河邊找鬼。 笑死沉御,一個(gè)胖子當(dāng)著我的面吹牛往核,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播嚷节,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼聂儒,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼虎锚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起衩婚,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤窜护,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后非春,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體柱徙,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年奇昙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了护侮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡储耐,死狀恐怖羊初,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情什湘,我是刑警寧澤长赞,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站闽撤,受9級(jí)特大地震影響得哆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜哟旗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一贩据、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧闸餐,春花似錦饱亮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蠕啄。三九已至场勤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間歼跟,已是汗流浹背和媳。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留哈街,地道東北人留瞳。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像骚秦,于是被迫代替她去往敵國和親她倘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子璧微,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

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

  • 前言 DOM是很慢的。真正的 DOM 元素非常龐大硬梁,這是因?yàn)闃?biāo)準(zhǔn)就是這么設(shè)計(jì)的前硫。而且操作它們的時(shí)候你要小心翼翼,輕...
    梁王io閱讀 1,109評(píng)論 0 1
  • 如何才教育出優(yōu)秀的小孩荧止,或者怎樣才能讓自己的孩子達(dá)到父母的標(biāo)準(zhǔn)屹电?這是每個(gè)父母都想得到的結(jié)果。女兒從出生到現(xiàn)在已接...
    康蘭閱讀 291評(píng)論 0 0
  • 現(xiàn)在我們知道數(shù)據(jù)、表和數(shù)據(jù)庫的關(guān)系了素邪,要學(xué)習(xí)如何創(chuàng)建這些東西外莲,就得先從數(shù)據(jù)庫開始,因?yàn)橛辛藬?shù)據(jù)庫才有表娘香,有了表才能...
    hothome99閱讀 402評(píng)論 0 0
  • 昨晚苍狰,女兒從外地學(xué)習(xí)半個(gè)月終于回家了,兩歲多的小外孫女一刻不停的跟著媽媽烘绽,她媽媽去衛(wèi)生間淋昭,她也強(qiáng)烈要求站在衛(wèi)生間等...
    微暖_781c閱讀 99評(píng)論 0 1
  • 昨晚夢(mèng)到了八十年代末某著名王姓人士翔忽。我和一個(gè)男孩子在破舊的筒樓巷子里走著,聽見王某人喊我們盏檐。我們抬頭歇式,看到了從窗戶...
    SodomOrphan閱讀 208評(píng)論 0 0