1.真实的DOM元素是非常庞大,这是因为浏览器的标准把DOM设计的非常复杂(一个DOM对象包含了许多属性,如上图所示)。当我们频繁地去做DOM更新,相应就会产生性能问题。
2.为了解决频繁操作DOM的性能问题,Virtual DOM就孕育而生了。虚拟的Virtual DOM就是用一个原生JS对象去描述一个DOM节点。因而它比创建一个真实DOM的代价要小很多。
3.可以在生命周期mounted中打印虚拟Dom
mounted() {
console.log(this._vnode);
},
4.__patch__方法是将新老VNode节点进行对比,然后将根据两者的比较结果进行最小单位地修改视图。patch的核心在于diff算法,这套算法可以高效地比较VNode的变更。
5.diff算法是一种通过同层的树节点进行比较的高效算法
特点:1. 比较只会在同层级进行,不会跨层级比较
2. 在diff比较的构成中,循环从两边向中间比较 -首尾指针法
6.据改变 ----触发--> setter---触发--->Dep.notify ---通知订阅者---> patch(oldvnode, newvnode)
之后判断新旧两个节点是否为同类标签,如果不是同类标签就直接替换;如果是同类标签的话,进一步执行patchVnode()方法,在这个方法内部,也是需要先判断一下新旧虚拟节点是否相同,如果相等,就直接return;如果不相等就需要分情况来比对,比对的原则就是以新虚拟节点的结果为准,分为以下几种情况:
oldvnode和newvnode都有文本节点---执行--->用新的文本节点替换旧文本节点
oldvnode没有子节点,newvnode有子节点---执行--->添加新的子节点
oldvnode有子节点,newvnode没有子节点---执行--->删除旧的子节点
oldvnode和newvnode都有子节点---执行--->updateChildren()方法
具体方法如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script>
// const vNode = 1
const vNode = {
tag: 'DIV',
attrs: {
id: 'app',
class: 'div'
},
text: '我是div盒子',
children: [
{
tag: 'SPAN',
attrs: {
class: 'span'
},
text: '我是span',
children: [
{
tag: 'A',
attrs: {
href: 'http://www.baidu.com'
},
text: '我是a',
children: []
}
]
},
{
tag: 'SPAN',
children: [
{ tag: 'A', children: [] },
{ tag: 'A', children: [] }
]
}
]
}
function render(vNode) {
// 创建元素
var dom = document.createElement(vNode.tag)
// 创建元素属性
if (vNode.attrs) {
Object.keys(vNode.attrs).forEach((key) => {
const value = vNode.attrs[key]
dom.setAttribute(key, value)
})
}
// 创建元素文本内容
if (vNode.text) {
dom.innerHTML = vNode.text
}
// 创建子元素
if (vNode.children) {
vNode.children.forEach((child) => {
dom.appendChild(render(child))
})
}
return dom
}
// 添加进body里
var body = document.querySelector('body')
body.appendChild(render(vNode))
</script>
</body>
</html>