在说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