简单来看一下virtualDom
终于我又回来了,想来想去不知道该写点什么,本来想仔细看看libuv的线程池,看得有点云里雾里的,最后决定了先写这个好啦,不然总觉得自己又偷懒。
熟么是vdom?
virtual dom顾名思义就是虚拟dom嘛,现在的大框架vue,react都用了这个。为啥用虚拟dom嘛?当然主要还是dom操作在浏览器中开销太大,为了减少并且细化dom操作而设计哒!这样能够极大的提升重绘性能。
虚拟dom怎么个虚拟法,当然是用js来虚拟啦。自从v8诞生以后js目前的效率是远超你想象的。
废话不多说,咱们就先来看看吧!
<ul id="list">
<li class="item">Item1</li>
<li class="item">Item2</li>
<li class="item">Item3</li>
</ul>
{
tag: 'ul',
attrs: {
id: 'list'
},
children: {
tag: 'li',
attrs: { className:'item' },
children: ['item1']
} , {
tag: 'li',
attrs: { className:'item' },
children: ['item2']
} , {
tag: 'li',
attrs: { className:'item' },
children: ['item3']
}
}
这就是一个模拟,用js对象来保存。其实这也有点像以前用xml来做网络传输,后面用json来做传输更为流行类似,虽然可读性并没有前者那么强,但是效率高啊。
传统方式与vdom对比
好哒,那咱们再来做个对比。内容就是一个列表,改变其中一个dom节点的操作
第一个咱们先用jQuery来试试
jQuery模拟
improt $ form 'jQuery'
let data = ['kalec', 'kali', 'john']
function rander(data) {
let $container = $('#container')
$container.html('')
let $ul = $('<ul>')
data.forEach(item => {
$ul.append($(`<li>${item}</li>`))
});
$container.append($ul)
}
$('#btn').click(() => {
data[2] = 'haha'
rander(data)
})
rander(data)
这其实已经算是jQuery最加性能的操作了,但是咱们看浏览器开发者工具
我滴妈呀,这不是整个节点都重绘了吗?搞毛啊…这真不是我们想要的结果。
下面我们还是有请vdom登场吧。
vdom由于当中diff算法比较复杂,待之后有时间单独更新。咱们就用社区的snabbdom一个来举例吧。
snabbdom测试vdom
import 'snabbdom'
import 'snabbdom-class'
import 'snabbdom-props'
import 'snabbdom-style'
import 'snabbdom-eventlisteners'
import 'h'
let snabbdom = window.snabbdom
let patch = snabbdom.init([
snabbdom_class,
snabbdom_props,
snabbdom_style,
snabbdom_eventlisteners
])
let h = snabbdom.h
let container = document.getElementById('container')
let vnode = h('ul#list', {}, [
h('li.item', {}, 'item1'),
h('li.item', {}, 'item2')
])
patch(container, vnode)
document.getElementById('btn').addEventListener('click', () => {
let newVnode = h('ul#list', {}, [
h('li.item', {}, 'item1'),
h('li.item', {}, '我是新加入滴'),
h('li.item', {}, 'item2')
])
patch(vnode, newVnode)
})
总结分析
这里我们就可以很直观的看到snabbdom的核心api,一个patch方法,一个h方法。
h方法的作用就是渲染虚拟dom结构,patch方法就是对比前后node节点内部的变化的地方,然后替换之。这种那里改变改那里的形式带来了更快的响应以及更流畅的体验。