一、什么是Virtual DOM
- 一句话表示就是用 JS 对象来模拟真实的 DOM 结构, 它应该包含三个内容, 分别为标签名(tag)、属性(props)、子元素对象(children), 下面是原生 DOM 与 VDOM 对比
<ul>
<li><p id='demo' class='p0'>test</p></li>
</ul>
{
tag: 'ul',
props: {},
children: [{
tag: 'li',
props: {},
children: [{
tag: 'p',
props: {
id: 'demo',
class: 'p0'
},
children: ['test']
}]
}]
}
二、Virtual DOM 跟原生 DOM 渲染的速度对比如何
- 在这里我做了个实验, Mock 1000 条基础数据, 然后用 simple-virtual-dom 做为VDOM 的基础库跟原生操作 DOM 做为比较
Mock 数据
- 测试循环添加 100 条数据, 发现使用原生的会比使用VDOM 操作要快
VDOM
原生
- 测试循环 100 次删除所有数据,先删之后再添加所有数据, 只记录删除数据的时间, 还是原生的操作会快一点
VDOM
原生
三、为什么要使用 Virtual DOM
- 我在知乎上找到尤大对这个问题的一些见解
- 原生 DOM 操作 vs. 通过框架封装操作, 这是一个性能 vs 可维护性的取舍. 框架的意义在于为你掩盖底层的 DOM 操作, 让你用更声明式的方式来描述你的目的, 从而让你的代码更容易维护
- 框架给你的保证是, 你在不需要手动优化的情况下, 我依然可以给你提供过得去的性能
- 将页面状态用 JS 对象的形式来表示, 然后配合不同的渲染工具, 实现跨平台渲染. 例如 React 使用 VDOM 实现服务端渲染(next)、浏览器渲染(react)、移动端渲染(react native)
- 为函数式的 UI 编程方式打开了大门
四、如何实现 Virtual DOM 算法
- VDOM 算法主要分 5 部分
- 构建 VDOM
const tree = el('ul', [
el('li', { class: 'demo' }, ['demo1']),
el('li', { class: 'demo' }, ['demo2'])
]);
- 通过 VDOM 构建原生 DOM
const element = tree.render();
containerElement.appendChild(element);
- 生成新的 VDOM
const newTree = el('ul', [
el('li', { class: 'demo' }, ['demo1']),
el('li', { class: 'demo' }, ['demo2']),
el('li', { class: 'demo' }, ['demo3'])
]);
- 比较 VDOM 树上的差异
const patches = diff(tree, newTree);
- 将差异更新到原生 DOM 上
patch(element, patches);
- 这是一个比较简单的例子, 在实际的运用中, 考虑的东西会更加多, 例如要处理事件监听的问题
参考资料: