dom
前端对 dom 太熟悉不过了,如下:
<div class="one">
<div class="two">
<a href="#">hello</a>
</div>
<p style="font-size: 20px;">world</p>
</div>
vdom
那什么是 vdom 呢? vdom 就是用 js 描述的 dom。比如上面的 dom 可以用下面的 js 对象描述。
{
// tag 表示的节点的名字, 是 div 节点害死 a,p 等节点
tag: 'div',
// props 表示节点上的属性
props: {
// className 表示 class, 因为 class 是关键词,行业通用写法, className === class
className: 'one'
},
// children 表示有孩子节点,如果孩子几点是文本,就直接 text 属性表示
children: [
{
tag: 'div',
props: {
className: 'two',
},
children: [
{
tag: 'a',
props: {
href: '#'
},
// a 节点里面的子节点是文本,故用 text 直接表示, 不用 children
text: 'hello'
}
]
},
{
tag: 'p',
props: {
style: 'font-size: 20px;'
},
text: 'word'
}
]
}
为什么有 vdom ?
vdom 首先是由 react 项目里面提出来的。在 react 之前,前端开发者都是用 Jquery 或者原生 js 直接操作 dom。操作 dom 是很耗时间和性能的,因为修改 dom 的后,游览器需要重新 回流 和 重绘,频繁的修改 dom,游览器所需要的开销很大,所以直接操作 dom 很慢。但是执行 js 却很快的。如果把 dom 操作放到 js 中去执行,再一次性去渲染到 dom 中,那必然快很多。所以 vdom 出现了。结合 diff 算法比对,最小化更新原生 dom 操作。所以现在 react vue 里面都用到了 vdom。
举一个简单的栗子
for(var i=0; i<10; i++) {
var div = document.createElement('div');
div.innerHTML = i;
document.getElementById('app').appendChild(div)
}
上面代码表示获取页面中一个 id 为 app 的 div,并往里面添加了 10 个新的 div,for 循环第一遍的时候,appendChild div 节点到页面中。游览器发现 dom 有改变,会立马重新渲染页面,发生 回流和重绘。游览器是不知道你后面还有第 2 次,第 3 次到。所以就一遍一遍的重新渲染,很耗性能,效率很低。
如果把创建 div 放到 vdom 里面操作,最后再 appendChild 到页面中,游览器只渲染了一次。是不是效率高很多呢。
总结
vdom 是基础面试中经常会问到的问题,面试官可能会给你一段 dom 结构,让你用 js 来描述这个 dom。所以参考上面的 vdom 的 js 描述。做到自己能用 js 手写描述 vdom。