什么是虚拟DOM?
用javaScript对象描述DOM的层次结构,DOM中的一切属性都在虚拟DOM中有对应的属性。
真实DOM:
<div class="box">
<h3>我是一个标题</h3>
<ul>
<li>西瓜</li>
<li>葡萄</li>
<li>香蕉</li>
</ul>
</div>
虚拟DOM:
{
"sel": "div",
"data": {
"class": {
"box": true
}
},
"children": [
{
"sel": "h3",
"data": {},
"text": "我是一个标题"
},
{
"sel": "ul",
"data": {},
"children": [
{ "sel": "li", "data": {}, "text": "西瓜" },
{ "sel": "li", "data": {}, "text": "葡萄" },
{ "sel": "li", "data": {}, "text": "香蕉" }
]}
]
}
diff是发生在虚拟DOM上的,新虚拟DOM和老虚拟DOM进行diff(精细化比较),算出应该如何最小量更新,最后反映到真正的DOM上。
为什么需要虚拟DOM?
用传统的原生api或jQuery去操作DOM时,浏览器会从构建DOM树开始从头到尾执行一遍流程。当你在一次操作时,需要更新10个DOM节点,浏览器没这么智能,收到第一个更新DOM请求后,并不知道后续还有9次更新操作,因此会马上执行流程,最终执行10次流程。
而通过虚拟DOM,同样更新10个DOM节点,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地的一个js对象中,最终将这个js对象一次性patch到DOM树上,避免大量的无谓计算。所以也可以把虚拟DOM理解为是真实DOM的缓存。
怎么产生虚拟DOM?
通过h函数来产生虚拟节点(vnode),比如这样调用h函数:
const vNode1 = h('a',{props:{href:'http://www.baidu.com'}},'百度')
将得到的虚拟节点为:
{ "sel": "a", "data": { props: { href: 'http://www.baidu.com' } }, "text": "百度" }
而真正的DOM节点为:
<a href="http://www.baidu.com">百度</a>
虚拟节点(vnode)有哪些属性?
Snabbdom的vnode是纯数据对象,通过vnode模块来创建,对象的属性包括:
{children : undefineddata : {}elm : undefinedkey : undefinedsel : " div "text : " 我是一个盒子 "}
vnode用于创建真实节点的数据包括:
元素类型
元素属性
元素的子节点
让我们来动手写写vnode
export default function (sel,data,children,text,elm){
let key = data.key
return {sel,data,children,text,elm,key}
}
我们注意到Snobbdom并没有直接暴露vnode对象,而是通过h()函数【渲染函数】,在h()函数里面返回时调用vnode,这里的源码使用了函数重载,我们尝试实现简单的h函数,就 第一个参数是选择器sel,第二个参数是数据data,第三个文本text或数组【会嵌套h函数】或对象【因为h函数返回的也是一个对象】
h('a',{},'')
h('a',{},[])
h('a',{},{})
思路:
1.判断参数的个数,不是3个那不行!
throw new Error('传入的参数不能