Virtual-DOM的理解

Virtual-DOM的理解

什麼是DOM?

在說Virtual-DOM以前,咱們來先說下什麼是DOM,DOM從字面上來理解是文檔對象模型。vue

W3C對DOM的定義是:「一個與系統平臺和編程語言無關的接口,程序和腳本能夠經過這個接口動態地訪問和修改文檔內容、結構和樣式。」node

而從上面的定義總結來看,DOM是接口,這個接口能夠操做文檔。react

而文檔呢就是Document,在HTML中的Document,能夠簡單理解成一個節點樹,而咱們要將這個節點樹映射成對象,而對象中天然就存在屬性和方法了,其中這些方法就讓咱們能夠操做文檔(好像說的仍是有點繞)git

什麼是Virtual-DOM?

Virtual-DOM翻譯過來就是虛擬DOM,而它其實能夠簡單理解爲,經過JS去建立的表示DOM的對象,而且未加載到真實頁面中github

  • virtual-dom = js對象
  • 未渲染到頁面中

有人說用virtual-dom比真實dom快,其實這是相對的,virtual-dom不少時候都不是最優的操做,但它具備普適性,在效率、可維護性之間達平衡算法

在網上看到一段代碼,比較簡潔的描述瞭如何去建立一個virtual-dom:編程

//創建一個VNode的對象
class VNode {
    constructor(tag, children, text) {
        this.tag = tag
        this.text = text
        this.children = children
    }

    render() {
        if (this.tag === '#text') {
            return document.createTextNode(this.text)
        }
        let el = document.createElement(this.tag)
        this.children.forEach(vChild => {
            el.appendChild(vChild.render())
        })
        return el
    }
}

function v(tag, children, text) {
    if (typeof children === 'string') {
        text = children
        children = []
    }
    return new VNode(tag, children, text)
}

/* let nodesData = { tag: 'div', children: [ { tag: 'p', children: [ { tag: 'span', children: [ { tag: '#text', text: 'baidu' } ] } ] }, { tag: 'span', children: [ { tag: '#text', text: 'alibaba' } ] } ] } */

let vNodes = v('div', [
    v('p', [
        v('span', [v('#text', 'baidu')])
    ]
    ),
    v('span', [
        v('#text', 'alibaba')
    ])
]);
console.log(vNodes.render())//創建真實DOM

// 對比DOM樹變動
function patchElement(parent, newVNode, oldVNode, index = 0) {
    if (!oldVNode) {
        parent.appendChild(newVNode.render())
    } else if (!newVNode) {
        parent.removeChild(parent.childNodes[index])
    } else if (newVNode.tag !== oldVNode.tag || newVNode.text !== oldVNode.text) {
        parent.replaceChild(newVNode.render(), parent.childNodes[index])
    } else {
        for (let i = 0; i < newVNode.children.length || i < oldVNode.children.length; i++) {
            patchElement(parent.childNodes[index], newVNode.children[i], oldVNode.children[i], i)
        }
    }
}


let vNodes1 = v('div', [
    v('p', [
        v('span', [v('#text', 'baidu')])
    ]
    ),
    v('span', [
        v('#text', 'ali')
    ])
]
)//虛擬DOM1

let vNodes2 = v('div', [
    v('p', [
        v('span', [
            v('#text', 'jd')
        ])
    ]
    ),
    v('span', [
        v('#text', 'baidu'),
        v('#text', 'map')
    ])
]
)//虛擬DOM2
const root = document.querySelector('#root')
patchElement(root, vNodes1) //對比更新
複製代碼

咱們從上面的代碼能夠清晰的看到 vdom的簡單流程app

vue2引入的vdom是基於snabbdom進行的修改而來,對於snabbdom的源碼解析,咱們能夠看這裏dom

react的diff算法,在16版本以前,與vue2應該大同小異 而在react16以後的fiber,採用了不一樣的方式編程語言

上面只是簡單的介紹了下virtual-dom的概念而已,而對於具體究竟是如何進行vdom之間的diff,纔是更核心的東西,咱們後續再去研究它

更多內容請看 blog

相關文章
相關標籤/搜索