vdom 概念
用JS模拟DOM结构。
DOM变化的对比,放在JS层来做。
提升重绘性能。
比如有abc 三个dom, 如果我们要删除b dom, 以前浏览器的做法是 全部删除abc dom , 然后 在添加b dom 。这样做的成本会非常高。
用JS模拟 dom
例如下面的一个dom 结构:
<ul id="list">
<li class="item">item1</li>
<li class="item">item2</li>
</ul>
这样的dom 结构,可以模拟为下面的JS :
let dom = {
tag: 'ul',
attrs: {
id: 'list'
},
children: [
{
tag: 'li',
attrs: {className: 'item'},
children: ['item1']
},
{
tag: 'li',
attrs: {className: 'item'},
children: ['item2']
}
]
}
浏览器操作dom 是花销非常大的。执行JS花销要小非常多,所以这就是为什么虚拟dom 出现的一个根本原因。
jquery实现virtual-dom
一个需求场景
1、数据生成表格。 2、随便修改一个信息,表格也会跟着修改。
<body>
<div id="container"></div>
<br>
<button id="btn-change">change</button>
<script>
let data = [
{
name: 'yanle',
age: '20',
address: '重庆'
},
{
name: 'yanle2',
age: '25',
address: '成都'
},
{
name: 'yanle3',
age: '27',
address: '深圳'
}
];
// 渲染函数
function render(data) {
let $container = document.getElementById('container');
$container.innerHTML = '';
let $table = document.createElement('table');
$table.setAttribute('border', true);
$table.insertAdjacentHTML('beforeEnd', `<tr>
<td>name</td>
<td>age</td>
<td>address</td>
</tr>`);
data.forEach(function (item) {
$table.insertAdjacentHTML('beforeEnd',
`<tr>
<td>${item.name}</td>
<td>${item.age}</td>
<td>${item.address}</td>
</tr>`
)
});
$container.appendChild($table);
}
// 修改信息
let button = document.getElementById('btn-change');
button.addEventListener('click', function () {
data[1].name = '徐老毕';
data[1].age = 30;
data[1].address = '深圳';
render(data);
});
render(data);
</script>
</body>
实际上上面的这段代码也是不符合预期的,因为每次使用render 方法,都会全部渲染整个table, 但是并未没有只渲染我们想要的第二行。
遇到的问题:
DOM 操作是非常 "昂贵" 的, JS 运行效率高。虚拟dom 的核心就是diff算法,对比出不同的dom数据,定点渲染不同的数据。