虚拟DOM
写一写,加深印象~
虚拟 DOM (Virtual DOM),简写vdom,vdom 是实现vue和React的重要基石。
DOM操作非常耗费性能,js执行速度很快(以前用jquery可以自行控制DOM操作的时机,手动调整)。
vue和react是数据驱动视图,如何有效控制DOM操作?
解决方案:vdom — 用js模拟DOM结构,计算出最小的变更,操作DOM
用js模拟DOM操作:
<div id='div1' class='container'>
<p>vdom</p>
<ul style='font-size:20px;'>
<li>a</li>
</ul>
</div>
{
tag: 'div',
props: {
className: 'container',
id: 'div1'
},
children: [
{
tag: 'p',
children: 'vdom'
},
{
tag: 'ul',
props: {style:'font-size: 20px'},
children: [
{
tag: 'li',
children: 'a'
}
//...
]
}
]
}
用js模拟DOM操作,没有严格的标准,基本上会遵循这个规律,tag元素标签、props属性(样式、事件……)、children子元素
如何使用?通过snabbdom
vue3.0重写了vdom的代码,优化了性能,但vdom的基本理念不变
像SnabbDOM这种库的虚拟DOM是如下的数据结构:
- sel 元素选择器
- data 元素属性
- children 元素子节点
- text 元素文本
- elm 对应dom元素
- key
snabbdom 不直接暴漏vnode对象,通过h包装处理。
snabbdom操作vdom的重点:
- h函数(h函数创建返回vnode结构)
- vnode数据结构
- patch函数
以下截取部分代码
<div id="container"></div>
<button id="btn-change">change</button>``
// 定义 h
const h = snabbdom.h
const container = document.getElementById('container')
// 生成 vnode
const vnode = h('ul#list', {}, [
h('li.item', {}, 'Item 1'),
h('li.item', {}, 'Item 2')
])
patch(container, vnode)
document.getElementById('btn-change').addEventListener('click', () => {
// 生成 newVnode
const newVnode = h('ul#list', {}, [
h('li.item', {}, 'Item 1'),
h('li.item', {}, 'Item B'),
h('li.item', {}, 'Item 3')
])
patch(vnode, newVnode)
// vnode = newVnode
// patch 之后,应该用新的覆盖现有的 vnode ,否则每次 change 都是新旧对比
})
vdom总结:
用JS模拟DOM结构(vnode)
新旧vnode对比,得出最小的更新范围,最后更新DOM(按需更新)
数据驱动视图的模式下,有效控制DOM操作
下节准备更新虚拟DOM—diff算法,
loading……
……
参考
https://github.com/snabbdom/snabbdom/
https://www.cnblogs.com/xuntu/p/6800547.html
https://www.cnblogs.com/dojo-lzz/p/8047742.html