虚拟dom :Virtual DOM 到底是个啥?我亲手撸了个小实验!

133 阅读3分钟

前段时间,我的项目里有个需求,要动态渲染一大串数据。刚开始用原生 DOM 操作,结果页面一卡一卡的,我直接傻眼了。后来折腾了一下 Virtual DOM,这性能提升直接让我惊掉下巴。 所以,Virtual DOM 到底是个啥?为什么用它会更快?今天就手撸个实验给你看!

为什么直接操作 DOM 会卡?

先上一段代码,我拿一个简单的 div 结构,打印出它的所有属性: 

console.log(document.createElement('div')); 

 打印结果直接铺满屏,DOM 上挂了一堆属性和方法,比如 `parentNode`、`innerHTML`、`appendChild`,还有各种奇奇怪怪的东西。这些属性虽然强大,但也意味着它非常笨重。

核心问题:每次 DOM 操作,浏览器需要重新解析、重绘,计算量大得可怕。如果每秒触发几十次操作,页面卡顿就是必然的结果。

Virtual DOM 到底是什么? 

听起来高大上,其实就是一个用 JavaScript 对象描述 DOM 的轻量化模型!

举个例子,把下面的 DOM:

用 Virtual DOM 表示成这样: 

看出来了吧?它只是把 DOM 结构抽象成了一个普通的 JavaScript 对象。而 JS 对象的操作成本,远远低于 DOM。

亲手实现一个简单的 Virtual DOM 

要理解它的原理,最好的方式就是自己动手实现一个小 Demo!

下面是一个简单的 VNode 定义:

这就是 Virtual DOM 的雏形,通过 JavaScript 对象描述 DOM 的结构,清晰明了,而且完全没有浏览器的负担。

Virtual DOM 如何高效更新页面? 

Virtual DOM 不会直接操作 DOM,而是通过以下几个步骤完成页面更新: 

1. 创建 Virtual DOM:通过 `VNode` 定义页面结构。 

2. Diff 算法对比新旧 Virtual DOM:找出需要更新的地方。 

3.Patch(打补丁):把变化应用到真实 DOM。 简单理解就是:先用 JS 模拟页面的变化,最后一次性更新真实 DOM,减少了直接操作的频率。 

实验:手写 Diff 算法 

为了让原理更直观,我手写了一个超简单的 Diff 算法,只对比同层节点: 

运行后会输出需要替换的内容,这样就避免了直接覆盖整个 DOM 的操作,大幅提升性能。 

总结 

 Virtual DOM 是真实 DOM 的抽象层,轻量、高效,避免了频繁的 DOM 操作。通过 diff 和 patch,Virtual DOM 能用最小的代价完成页面更新。 写这篇文章的时候,我发现了很多以前忽略的细节,比如如何高效对比两个节点,如何批量应用更新。总之,Virtual DOM 不只是 Vue 和 React 的黑科技,它的核心思想非常值得借鉴。

觉得有帮助的话,点个赞吧!下次我来讲讲 Vue 是怎么实现 Diff 算法的,干货满满!