在說Virtual-DOM以前,咱們來先說下什麼是DOM,DOM從字面上來理解是文檔對象模型。vue
W3C對DOM的定義是:「一個與系統平臺和編程語言無關的接口,程序和腳本能夠經過這個接口動態地訪問和修改文檔內容、結構和樣式。」node
而從上面的定義總結來看,DOM是接口,這個接口能夠操做文檔。react
而文檔呢就是Document,在HTML中的Document,能夠簡單理解成一個節點樹,而咱們要將這個節點樹映射成對象,而對象中天然就存在屬性和方法了,其中這些方法就讓咱們能夠操做文檔(好像說的仍是有點繞)git
Virtual-DOM翻譯過來就是虛擬DOM,而它其實能夠簡單理解爲,經過JS去建立的表示DOM的對象,而且未加載到真實頁面中github
有人說用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